home *** CD-ROM | disk | FTP | other *** search
/ Enter 2001 April / EnterCD4.iso / Update / SQL Server SP3 / sql70sp3i.exe / INSTALL / sp3_tools.sql < prev    next >
Encoding:
Text (UTF-16)  |  2000-10-18  |  223.7 KB  |  2,480 lines

  1. /*------------------------------------------------------------------------------
  2.  
  3. SP3_TOOLS.SQL
  4.  
  5. THIS SCRIPT TAKES THE TOOLS SYSTEM STORED PROCEDURES FROM 7.0, SP1, SP2 to SP3.
  6.  
  7. Changes in this file are organized as follows (please maintain):
  8.     SYSTEM OBJECTS (INSTMSDB.SQL)    
  9.  
  10. Notes:
  11. + Catalog-updates and sp_MS_upd_sysobj_category are enabled for the entire
  12.     file.  Do not disable or re-enable them.  Please do not change set options.
  13.  
  14. ------------------------------------------------------------------------------*/
  15.  
  16.  
  17. --------------------------------------------------------------------------------
  18. -- VERIFY Server is started in single-user-mode (catalog-updates enabled), and
  19. --    start marking of system-objects.
  20. --------------------------------------------------------------------------------
  21. use master
  22. go
  23.  
  24. exec dbo.sp_configure 'allow updates',1
  25. go
  26.  
  27. reconfigure with override
  28. go
  29.  
  30. exec sp_MS_upd_sysobj_category 1
  31. go
  32.  
  33. --------------------------------------------------------------------------------
  34. --.    Common system objects (instmsdb.sql)
  35. --------------------------------------------------------------------------------
  36. use msdb
  37. go
  38.  
  39. /**************************************************************/
  40. /* SYSCACHEDCREDENTIALS                                       */
  41. /*                                                            */
  42. /**************************************************************/
  43.  
  44. IF (NOT EXISTS (SELECT *
  45.                 FROM msdb.dbo.sysobjects
  46.                 WHERE (name = N'syscachedcredentials')
  47.                   AND (type = 'U')))
  48. BEGIN
  49.   CREATE TABLE syscachedcredentials
  50.   (
  51.   login_name          sysname      NOT NULL PRIMARY KEY,
  52.   has_server_access   BIT          NOT NULL DEFAULT 0,
  53.   is_sysadmin_member  BIT          NOT NULL DEFAULT 0,
  54.   cachedate           DATETIME     NOT NULL DEFAULT getdate()
  55.   )
  56. END
  57. go
  58.  
  59. /**************************************************************/
  60. /* SP_SQLAGENT_HAS_SERVER_ACCESS                              */
  61. /**************************************************************/
  62.  
  63. PRINT ''
  64. PRINT 'Creating procedure sp_sqlagent_has_server_access...'
  65. go
  66. IF (EXISTS (SELECT *
  67.             FROM msdb.dbo.sysobjects
  68.             WHERE (name = 'sp_sqlagent_has_server_access')
  69.               AND (type = 'P')))
  70.   DROP PROCEDURE sp_sqlagent_has_server_access
  71. go
  72. CREATE PROCEDURE sp_sqlagent_has_server_access
  73.   @login_name         sysname = NULL,
  74.   @is_sysadmin_member INT     = NULL OUTPUT
  75. AS
  76. BEGIN
  77.   DECLARE @has_server_access BIT
  78.   DECLARE @is_sysadmin       BIT
  79.   DECLARE @actual_login_name sysname
  80.   DECLARE @cachedate         DATETIME
  81.  
  82.   SET NOCOUNT ON
  83.  
  84.   SELECT @cachedate = NULL
  85.  
  86.   -- remove expired entries from the cache
  87.   DELETE msdb.dbo.syscachedcredentials
  88.   WHERE  DATEDIFF(MINUTE, cachedate, GETDATE()) >= 29
  89.  
  90.   -- query the cache
  91.   SELECT  @is_sysadmin = is_sysadmin_member,
  92.           @has_server_access = has_server_access,
  93.           @cachedate = cachedate
  94.   FROM    msdb.dbo.syscachedcredentials
  95.   WHERE   login_name = @login_name
  96.   AND     DATEDIFF(MINUTE, cachedate, GETDATE()) < 29
  97.  
  98.   IF (@cachedate IS NOT NULL)
  99.   BEGIN
  100.     -- no output variable
  101.     IF (@is_sysadmin_member IS NULL)
  102.     BEGIN
  103.       -- Return result row
  104.       SELECT has_server_access = @has_server_access,
  105.              is_sysadmin       = @is_sysadmin,
  106.              actual_login_name = @login_name
  107.       RETURN
  108.     END
  109.     ELSE
  110.     BEGIN
  111.       SELECT @is_sysadmin_member = @is_sysadmin
  112.       RETURN
  113.     END
  114.   END -- select from cache
  115.  
  116.   CREATE TABLE #xp_results
  117.   (
  118.   account_name      sysname      NOT NULL PRIMARY KEY,
  119.   type              NVARCHAR(10) NOT NULL,
  120.   privilege         NVARCHAR(10) NOT NULL,
  121.   mapped_login_name sysname      NOT NULL,
  122.   permission_path   sysname      NULL
  123.   )
  124.  
  125.   -- Set defaults
  126.   SELECT @has_server_access = 0
  127.   SELECT @is_sysadmin = 0
  128.   SELECT @actual_login_name = FORMATMESSAGE(14205)
  129.  
  130.   IF (@login_name IS NULL)
  131.   BEGIN
  132.     SELECT has_server_access = 1,
  133.            is_sysadmin       = IS_SRVROLEMEMBER(N'sysadmin'),
  134.            actual_login_name = SUSER_SNAME()
  135.     RETURN
  136.   END
  137.  
  138.   IF (@login_name LIKE '%\%')
  139.   BEGIN
  140.     -- Handle the LocalSystem account ('NT AUTHORITY\SYSTEM') as a special case
  141.     IF (UPPER(@login_name) = N'NT AUTHORITY\SYSTEM')
  142.     BEGIN
  143.       IF (EXISTS (SELECT *
  144.                   FROM master.dbo.syslogins
  145.                   WHERE (UPPER(loginname) = N'BUILTIN\ADMINISTRATORS')))
  146.       BEGIN
  147.         SELECT @has_server_access = hasaccess,
  148.                @is_sysadmin = sysadmin,
  149.                @actual_login_name = loginname
  150.         FROM master.dbo.syslogins
  151.         WHERE (UPPER(loginname) = N'BUILTIN\ADMINISTRATORS')
  152.       END
  153.     END
  154.     ELSE
  155.     BEGIN
  156.       -- Check if the NT login has been explicitly denied access
  157.       IF (EXISTS (SELECT *
  158.                   FROM master.dbo.syslogins
  159.                   WHERE (loginname = @login_name)
  160.                     AND (denylogin = 1)))
  161.       BEGIN
  162.         SELECT @has_server_access = 0,
  163.                @is_sysadmin = sysadmin,
  164.                @actual_login_name = loginname
  165.         FROM master.dbo.syslogins
  166.         WHERE (loginname = @login_name)
  167.       END
  168.       ELSE
  169.       BEGIN
  170.         -- Call xp_logininfo to determine server access
  171.         INSERT INTO #xp_results
  172.         EXECUTE master.dbo.xp_logininfo @login_name
  173.  
  174.         SELECT @has_server_access = CASE COUNT(*)
  175.                                       WHEN 0 THEN 0
  176.                                       ELSE 1
  177.                                     END
  178.         FROM #xp_results
  179.         SELECT @actual_login_name = mapped_login_name,
  180.                @is_sysadmin = CASE UPPER(privilege)
  181.                                 WHEN 'ADMIN' THEN 1
  182.                                 ELSE 0
  183.                              END
  184.         FROM #xp_results
  185.       END
  186.     END
  187.   END
  188.   ELSE
  189.   BEGIN
  190.     -- Standard login
  191.     IF (EXISTS (SELECT *
  192.                 FROM master.dbo.syslogins
  193.                 WHERE (loginname = @login_name)))
  194.     BEGIN
  195.       SELECT @has_server_access = hasaccess,
  196.              @is_sysadmin = sysadmin,
  197.              @actual_login_name = loginname
  198.       FROM master.dbo.syslogins
  199.       WHERE (loginname = @login_name)
  200.     END
  201.   END
  202.  
  203.   -- update the cache only if something is found
  204.   IF  (UPPER(@actual_login_name) <> '(UNKNOWN)')
  205.   BEGIN
  206.     IF EXISTS (SELECT * FROM msdb.dbo.syscachedcredentials WHERE login_name = @login_name)
  207.     BEGIN
  208.       UPDATE msdb.dbo.syscachedcredentials
  209.       SET    has_server_access = @has_server_access,
  210.              is_sysadmin_member = @is_sysadmin,
  211.              cachedate = GETDATE()
  212.       WHERE  login_name = @login_name
  213.     END
  214.     ELSE
  215.     BEGIN
  216.       INSERT INTO msdb.dbo.syscachedcredentials(login_name, has_server_access, is_sysadmin_member) 
  217.       VALUES(@login_name, @has_server_access, @is_sysadmin)
  218.     END
  219.   END
  220.  
  221.   IF (@is_sysadmin_member IS NULL)
  222.     -- Return result row
  223.     SELECT has_server_access = @has_server_access,
  224.            is_sysadmin       = @is_sysadmin,
  225.            actual_login_name = @actual_login_name
  226.   ELSE
  227.     -- output variable only
  228.     SELECT @is_sysadmin_member = @is_sysadmin
  229. END
  230. go
  231.  
  232. /**************************************************************/
  233. /* SP_ENUM_SQLAGENT_SUBSYSTEMS                                */
  234. /**************************************************************/
  235.  
  236. PRINT ''
  237. PRINT 'Creating procedure sp_enum_sqlagent_subsystems...'
  238. go
  239. IF (EXISTS (SELECT *
  240.             FROM msdb.dbo.sysobjects
  241.             WHERE (name = N'sp_enum_sqlagent_subsystems')
  242.               AND (type = 'P')))
  243.   DROP PROCEDURE sp_enum_sqlagent_subsystems
  244. go
  245. CREATE PROCEDURE sp_enum_sqlagent_subsystems
  246. AS
  247. BEGIN
  248.   DECLARE @part                  NVARCHAR(300)
  249.   DECLARE @fmt                   NVARCHAR(300)
  250.   DECLARE @subsystem             NVARCHAR(40)
  251.   DECLARE @replication_installed INT
  252.  
  253.   SET NOCOUNT ON
  254.  
  255.   CREATE TABLE #xp_results (subsystem   NVARCHAR(40)  NOT NULL,
  256.                             description NVARCHAR(300) NOT NULL)
  257.   CREATE TABLE #sp_enum_ss_temp (subsystem          NVARCHAR(40) NOT NULL,
  258.                                  description        NVARCHAR(80) NOT NULL,
  259.                                  subsystem_dll      NVARCHAR(80) NULL,
  260.                                  agent_exe          NVARCHAR(80) NULL,
  261.                                  start_entry_point  NVARCHAR(30) NULL,
  262.                                  event_entry_point  NVARCHAR(30) NULL,
  263.                                  stop_entry_point   NVARCHAR(30) NULL,
  264.                                  max_worker_threads INT          NULL)
  265.  
  266.   -- Check if replication is installed
  267.   EXECUTE master.dbo.xp_regread N'HKEY_LOCAL_MACHINE',
  268.                                 N'SOFTWARE\Microsoft\MSSQLServer\Replication',
  269.                                 N'IsInstalled',
  270.                                  @replication_installed OUTPUT,
  271.                                 N'no_output'
  272.   SELECT @replication_installed = ISNULL(@replication_installed, 0)
  273.  
  274.   INSERT INTO #xp_results
  275.   EXECUTE master.dbo.xp_regenumvalues N'HKEY_LOCAL_MACHINE', N'SOFTWARE\Microsoft\MSSQLServer\SQLServerAgent\SubSystems'
  276.  
  277.   IF (@replication_installed = 0)
  278.   BEGIN
  279.     DELETE FROM #xp_results
  280.     WHERE (subsystem IN (N'Distribution', N'LogReader', N'Merge', N'Snapshot'))
  281.   END
  282.  
  283.   DECLARE all_subsystems CURSOR LOCAL
  284.   FOR
  285.   SELECT subsystem, description
  286.   FROM #xp_results
  287.  
  288.   OPEN all_subsystems
  289.   FETCH NEXT FROM all_subsystems INTO @subsystem, @part
  290.   WHILE (@@fetch_status = 0)
  291.   BEGIN
  292.     IF (@subsystem = N'TSQL')
  293.       INSERT INTO #sp_enum_ss_temp VALUES (N'TSQL', FORMATMESSAGE(14556), FORMATMESSAGE(14557), FORMATMESSAGE(14557), FORMATMESSAGE(14557), FORMATMESSAGE(14557), FORMATMESSAGE(14557), CONVERT(INT, @part))
  294.     ELSE
  295.     BEGIN
  296.       SELECT @fmt = N''
  297.       WHILE (CHARINDEX(N',', @part) > 0)
  298.       BEGIN
  299.         SELECT @fmt = @fmt + 'N''' + SUBSTRING(@part, 1, CHARINDEX(N',', @part) - 1) + ''', '
  300.         SELECT @part = RIGHT(@part, (DATALENGTH(@part) / 2) - CHARINDEX(N',', @part))
  301.       END
  302.       SELECT @fmt = @fmt + @part
  303.       IF (DATALENGTH(@fmt) > 0)
  304.         INSERT INTO #sp_enum_ss_temp
  305.         EXECUTE(N'SELECT ''' + @subsystem + N''', N'''', ' + @fmt) 
  306.     END
  307.     FETCH NEXT FROM all_subsystems INTO @subsystem, @part
  308.   END
  309.   DEALLOCATE all_subsystems
  310.  
  311.   UPDATE #sp_enum_ss_temp SET description = FORMATMESSAGE(14550)
  312.   WHERE (subsystem = N'CmdExec')
  313.   UPDATE #sp_enum_ss_temp SET description = FORMATMESSAGE(14551)
  314.   WHERE (subsystem = N'Snapshot')
  315.   UPDATE #sp_enum_ss_temp SET description = FORMATMESSAGE(14552)
  316.   WHERE (subsystem = N'LogReader')
  317.   UPDATE #sp_enum_ss_temp SET description = FORMATMESSAGE(14553)
  318.   WHERE (subsystem = N'Distribution')
  319.   UPDATE #sp_enum_ss_temp SET description = FORMATMESSAGE(14554)
  320.   WHERE (subsystem = N'Merge')
  321.   UPDATE #sp_enum_ss_temp SET description = FORMATMESSAGE(14555)
  322.   WHERE (subsystem = N'ActiveScripting')
  323.  
  324.   -- 'TSQL' is always available (since it's a built-in subsystem), so we explicity add it
  325.   -- to the result set
  326.   IF (NOT EXISTS (SELECT * 
  327.                   FROM #sp_enum_ss_temp 
  328.                   WHERE (subsystem = N'TSQL')))
  329.     INSERT INTO #sp_enum_ss_temp VALUES (N'TSQL', FORMATMESSAGE(14556), FORMATMESSAGE(14557), FORMATMESSAGE(14557), FORMATMESSAGE(14557), FORMATMESSAGE(14557), FORMATMESSAGE(14557), CASE (PLATFORM() & 0x2) WHEN 0x2 THEN 10 ELSE 20 END) -- Worker thread rule should match DEF_REG_MAX_TSQL_WORKER_THREADS
  330.  
  331.   SELECT subsystem,
  332.          description,
  333.          subsystem_dll,
  334.          agent_exe,
  335.          start_entry_point,
  336.          event_entry_point,
  337.          stop_entry_point,
  338.          max_worker_threads
  339.   FROM #sp_enum_ss_temp
  340.   ORDER BY subsystem
  341. END
  342. go
  343.  
  344. /**************************************************************/
  345. /* SP_GET_SQLAGENT_PROPERTIES                                 */
  346. /**************************************************************/
  347.  
  348. PRINT ''
  349. PRINT 'Creating procedure sp_get_sqlagent_properties...'
  350. go
  351. IF (EXISTS (SELECT *
  352.             FROM msdb.dbo.sysobjects
  353.             WHERE (name = N'sp_get_sqlagent_properties')
  354.               AND (type = 'P')))
  355.   DROP PROCEDURE sp_get_sqlagent_properties
  356. go
  357. CREATE PROCEDURE sp_get_sqlagent_properties
  358. AS
  359. BEGIN
  360.   DECLARE @auto_start                  INT
  361.   DECLARE @startup_account             NVARCHAR(100)
  362.   DECLARE @msx_server_name             NVARCHAR(30)
  363.  
  364.   -- Non-SQLDMO exposed properties
  365.   DECLARE @sqlserver_restart           INT
  366.   DECLARE @jobhistory_max_rows         INT
  367.   DECLARE @jobhistory_max_rows_per_job INT
  368.   DECLARE @errorlog_file               NVARCHAR(255)
  369.   DECLARE @errorlogging_level          INT
  370.   DECLARE @error_recipient             NVARCHAR(30)
  371.   DECLARE @monitor_autostart           INT
  372.   DECLARE @local_host_server           NVARCHAR(30)
  373.   DECLARE @job_shutdown_timeout        INT 
  374.   DECLARE @cmdexec_account             VARBINARY(64)
  375.   DECLARE @regular_connections         INT
  376.   DECLARE @host_login_name             sysname
  377.   DECLARE @host_login_password         VARBINARY(512)
  378.   DECLARE @login_timeout               INT
  379.   DECLARE @idle_cpu_percent            INT
  380.   DECLARE @idle_cpu_duration           INT
  381.   DECLARE @oem_errorlog                INT
  382.   DECLARE @sysadmin_only               INT
  383.   DECLARE @email_profile               NVARCHAR(64)
  384.   DECLARE @email_save_in_sent_folder   INT
  385.   DECLARE @cpu_poller_enabled          INT     
  386.  
  387.   SET NOCOUNT ON
  388.  
  389.   -- NOTE: We return all SQLServerAgent properties at one go for performance reasons
  390.  
  391.   -- Read the values from the registry
  392.   IF ((PLATFORM() & 0x1) = 0x1) -- NT
  393.   BEGIN
  394.     EXECUTE master.dbo.xp_regread N'HKEY_LOCAL_MACHINE',
  395.                                   N'SYSTEM\CurrentControlSet\Services\SQLServerAgent',
  396.                                   N'Start',
  397.                                    @auto_start OUTPUT,
  398.                                   N'no_output'
  399.     EXECUTE master.dbo.xp_regread N'HKEY_LOCAL_MACHINE',
  400.                                   N'SYSTEM\CurrentControlSet\Services\SQLServerAgent',
  401.                                   N'ObjectName',
  402.                                    @startup_account OUTPUT,
  403.                                   N'no_output'
  404.   END
  405.   ELSE
  406.   BEGIN
  407.     SELECT @auto_start = 3 -- Manual start
  408.     SELECT @startup_account = NULL
  409.   END
  410.   EXECUTE master.dbo.xp_regread N'HKEY_LOCAL_MACHINE',
  411.                                 N'SOFTWARE\Microsoft\MSSQLServer\SQLServerAgent',
  412.                                 N'MSXServerName',
  413.                                  @msx_server_name OUTPUT,
  414.                                 N'no_output'
  415.  
  416.   -- Non-SQLDMO exposed properties
  417.   EXECUTE master.dbo.xp_regread N'HKEY_LOCAL_MACHINE',
  418.                                 N'SOFTWARE\Microsoft\MSSQLServer\SQLServerAgent',
  419.                                 N'RestartSQLServer',
  420.                                  @sqlserver_restart OUTPUT,
  421.                                 N'no_output'
  422.   EXECUTE master.dbo.xp_regread N'HKEY_LOCAL_MACHINE',
  423.                                 N'SOFTWARE\Microsoft\MSSQLServer\SQLServerAgent',
  424.                                 N'JobHistoryMaxRows',
  425.                                  @jobhistory_max_rows OUTPUT,
  426.                                 N'no_output'
  427.   EXECUTE master.dbo.xp_regread N'HKEY_LOCAL_MACHINE',
  428.                                 N'SOFTWARE\Microsoft\MSSQLServer\SQLServerAgent',
  429.                                 N'JobHistoryMaxRowsPerJob',
  430.                                  @jobhistory_max_rows_per_job OUTPUT,
  431.                                 N'no_output'
  432.   EXECUTE master.dbo.xp_regread N'HKEY_LOCAL_MACHINE',
  433.                                 N'SOFTWARE\Microsoft\MSSQLServer\SQLServerAgent',
  434.                                 N'ErrorLogFile',
  435.                                  @errorlog_file OUTPUT,
  436.                                 N'no_output'
  437.   EXECUTE master.dbo.xp_regread N'HKEY_LOCAL_MACHINE',
  438.                                 N'SOFTWARE\Microsoft\MSSQLServer\SQLServerAgent',
  439.                                 N'ErrorLoggingLevel',
  440.                                  @errorlogging_level OUTPUT,
  441.                                 N'no_output'
  442.   EXECUTE master.dbo.xp_regread N'HKEY_LOCAL_MACHINE',
  443.                                 N'SOFTWARE\Microsoft\MSSQLServer\SQLServerAgent',
  444.                                 N'ErrorMonitor',
  445.                                  @error_recipient OUTPUT,
  446.                                 N'no_output'
  447.   EXECUTE master.dbo.xp_regread N'HKEY_LOCAL_MACHINE',
  448.                                 N'SOFTWARE\Microsoft\MSSQLServer\SQLServerAgent',
  449.                                 N'MonitorAutoStart',
  450.                                  @monitor_autostart OUTPUT,
  451.                                 N'no_output'
  452.   EXECUTE master.dbo.xp_regread N'HKEY_LOCAL_MACHINE',
  453.                                 N'SOFTWARE\Microsoft\MSSQLServer\SQLServerAgent',
  454.                                 N'ServerHost',
  455.                                  @local_host_server OUTPUT,
  456.                                 N'no_output'
  457.   EXECUTE master.dbo.xp_regread N'HKEY_LOCAL_MACHINE',
  458.                                 N'SOFTWARE\Microsoft\MSSQLServer\SQLServerAgent',
  459.                                 N'JobShutdownTimeout',
  460.                                  @job_shutdown_timeout OUTPUT,
  461.                                 N'no_output'
  462.   EXECUTE master.dbo.xp_regread N'HKEY_LOCAL_MACHINE',
  463.                                 N'SOFTWARE\Microsoft\MSSQLServer\SQLServerAgent',
  464.                                 N'CmdExecAccount',
  465.                                  @cmdexec_account OUTPUT,
  466.                                 N'no_output'
  467.   EXECUTE master.dbo.xp_regread N'HKEY_LOCAL_MACHINE',
  468.                                 N'SOFTWARE\Microsoft\MSSQLServer\SQLServerAgent',
  469.                                 N'RegularConnections',
  470.                                  @regular_connections OUTPUT,
  471.                                 N'no_output'
  472.   EXECUTE master.dbo.xp_regread N'HKEY_LOCAL_MACHINE',
  473.                                 N'SOFTWARE\Microsoft\MSSQLServer\SQLServerAgent',
  474.                                 N'HostLoginID',
  475.                                  @host_login_name OUTPUT,
  476.                                 N'no_output'
  477.   EXECUTE master.dbo.xp_regread N'HKEY_LOCAL_MACHINE',
  478.                                 N'SOFTWARE\Microsoft\MSSQLServer\SQLServerAgent',
  479.                                 N'HostPassword',
  480.                                  @host_login_password OUTPUT,
  481.                                 N'no_output'
  482.   EXECUTE master.dbo.xp_regread N'HKEY_LOCAL_MACHINE',
  483.                                 N'SOFTWARE\Microsoft\MSSQLServer\SQLServerAgent',
  484.                                 N'LoginTimeout',
  485.                                  @login_timeout OUTPUT,
  486.                                 N'no_output'
  487.   EXECUTE master.dbo.xp_regread N'HKEY_LOCAL_MACHINE',
  488.                                 N'SOFTWARE\Microsoft\MSSQLServer\SQLServerAgent',
  489.                                 N'IdleCPUPercent',
  490.                                  @idle_cpu_percent OUTPUT,
  491.                                 N'no_output'
  492.   EXECUTE master.dbo.xp_regread N'HKEY_LOCAL_MACHINE',
  493.                                 N'SOFTWARE\Microsoft\MSSQLServer\SQLServerAgent',
  494.                                 N'IdleCPUDuration',
  495.                                  @idle_cpu_duration OUTPUT,
  496.                                 N'no_output'
  497.   EXECUTE master.dbo.xp_regread N'HKEY_LOCAL_MACHINE',
  498.                                 N'SOFTWARE\Microsoft\MSSQLServer\SQLServerAgent',
  499.                                 N'OemErrorLog',
  500.                                  @oem_errorlog OUTPUT,
  501.                                 N'no_output'
  502.   EXECUTE master.dbo.xp_regread N'HKEY_LOCAL_MACHINE',
  503.                                 N'SOFTWARE\Microsoft\MSSQLServer\SQLServerAgent',
  504.                                 N'SysAdminOnly',
  505.                                  @sysadmin_only OUTPUT,
  506.                                 N'no_output'
  507.   EXECUTE master.dbo.xp_regread N'HKEY_LOCAL_MACHINE',
  508.                                 N'SOFTWARE\Microsoft\MSSQLServer\SQLServerAgent',
  509.                                 N'EmailProfile',
  510.                                  @email_profile OUTPUT,
  511.                                 N'no_output'
  512.   EXECUTE master.dbo.xp_regread N'HKEY_LOCAL_MACHINE',
  513.                                 N'SOFTWARE\Microsoft\MSSQLServer\SQLServerAgent',
  514.                                 N'EmailSaveSent',
  515.                                  @email_save_in_sent_folder OUTPUT,
  516.                                 N'no_output'
  517.   EXECUTE master.dbo.xp_regread N'HKEY_LOCAL_MACHINE',
  518.                                 N'SOFTWARE\Microsoft\MSSQLServer\SQLServerAgent',
  519.                                 N'CoreEngineMask',
  520.                                  @cpu_poller_enabled OUTPUT,
  521.                                 N'no_output'
  522.   IF (@cpu_poller_enabled IS NOT NULL)
  523.     SELECT @cpu_poller_enabled = CASE WHEN (@cpu_poller_enabled & 32) = 32 THEN 0 ELSE 1 END
  524.  
  525.   -- Return the values to the client
  526.   SELECT auto_start = CASE @auto_start
  527.                         WHEN 2 THEN 1 -- 2 means auto-start
  528.                         WHEN 3 THEN 0 -- 3 means don't auto-start
  529.                         ELSE 0        -- Safety net
  530.                       END,
  531.          msx_server_name = @msx_server_name,
  532.          sqlagent_type = (SELECT CASE
  533.                                     WHEN (COUNT(*) = 0) AND (ISNULL(DATALENGTH(@msx_server_name), 0) = 0) THEN 1 -- Standalone
  534.                                     WHEN (COUNT(*) = 0) AND (ISNULL(DATALENGTH(@msx_server_name), 0) > 0) THEN 2 -- TSX
  535.                                     WHEN (COUNT(*) > 0) AND (ISNULL(DATALENGTH(@msx_server_name), 0) = 0) THEN 3 -- MSX
  536.                                     WHEN (COUNT(*) > 0) AND (ISNULL(DATALENGTH(@msx_server_name), 0) > 0) THEN 0 -- Multi-Level MSX (currently invalid)
  537.                                     ELSE 0 -- Invalid
  538.                                   END
  539.                            FROM msdb.dbo.systargetservers),
  540.          startup_account = @startup_account,
  541.  
  542.          -- Non-SQLDMO exposed properties
  543.          sqlserver_restart = @sqlserver_restart,
  544.          jobhistory_max_rows = @jobhistory_max_rows,
  545.          jobhistory_max_rows_per_job = @jobhistory_max_rows_per_job,
  546.          errorlog_file = @errorlog_file,
  547.          errorlogging_level = ISNULL(@errorlogging_level, 7),
  548.          error_recipient = @error_recipient,
  549.          monitor_autostart = ISNULL(@monitor_autostart, 0),
  550.          local_host_server = @local_host_server,
  551.          job_shutdown_timeout = ISNULL(@job_shutdown_timeout, 15),
  552.          cmdexec_account = @cmdexec_account,
  553.          regular_connections = ISNULL(@regular_connections, 0),
  554.          host_login_name = @host_login_name,
  555.          host_login_password = @host_login_password,
  556.          login_timeout = ISNULL(@login_timeout, 30),
  557.          idle_cpu_percent = ISNULL(@idle_cpu_percent, 10),
  558.          idle_cpu_duration = ISNULL(@idle_cpu_duration, 600),
  559.          oem_errorlog = ISNULL(@oem_errorlog, 0),
  560.          sysadmin_only = ISNULL(@sysadmin_only, 0),
  561.          email_profile = @email_profile,
  562.          email_save_in_sent_folder = ISNULL(@email_save_in_sent_folder, 0),
  563.          cpu_poller_enabled = ISNULL(@cpu_poller_enabled, 0)
  564. END
  565. go
  566.  
  567. /**************************************************************/
  568. /* SP_SET_SQLAGENT_PROPERTIES                                 */
  569. /**************************************************************/
  570.  
  571. PRINT ''
  572. PRINT 'Creating procedure sp_set_sqlagent_properties...'
  573. go
  574. IF (EXISTS (SELECT *
  575.             FROM msdb.dbo.sysobjects
  576.             WHERE (name = N'sp_set_sqlagent_properties')
  577.               AND (type = 'P')))
  578.   DROP PROCEDURE sp_set_sqlagent_properties
  579. go
  580. CREATE PROCEDURE sp_set_sqlagent_properties
  581.   @auto_start                  INT           = NULL, -- 1 or 0
  582.  
  583.   -- Non-SQLDMO exposed properties
  584.   @sqlserver_restart           INT           = NULL, -- 1 or 0
  585.   @jobhistory_max_rows         INT           = NULL, -- No maximum = -1, otherwise must be > 1
  586.   @jobhistory_max_rows_per_job INT           = NULL, -- 1 to @jobhistory_max_rows
  587.   @errorlog_file               NVARCHAR(255) = NULL, -- Full drive\path\name of errorlog file
  588.   @errorlogging_level          INT           = NULL, -- 1 = error, 2 = warning, 4 = information
  589.   @error_recipient             NVARCHAR(30)  = NULL, -- Network address of error popup recipient 
  590.   @monitor_autostart           INT           = NULL, -- 1 or 0
  591.   @local_host_server           NVARCHAR(30)  = NULL, -- Alias of local host server
  592.   @job_shutdown_timeout        INT           = NULL, -- 5 to 600 seconds
  593.   @cmdexec_account             VARBINARY(64) = NULL, -- CmdExec account information
  594.   @regular_connections         INT           = NULL, -- 1 or 0
  595.   @host_login_name             sysname       = NULL, -- Login name (if regular_connections = 1) 
  596.   @host_login_password         VARBINARY(512)= NULL, -- Login password (if regular_connections = 1) 
  597.   @login_timeout               INT           = NULL, -- 5 to 45 (seconds)
  598.   @idle_cpu_percent            INT           = NULL, -- 1 to 100
  599.   @idle_cpu_duration           INT           = NULL, -- 20 to 86400 seconds
  600.   @oem_errorlog                INT           = NULL, -- 1 or 0
  601.   @sysadmin_only               INT           = NULL, -- 1 or 0
  602.   @email_profile               NVARCHAR(64)  = NULL, -- Email profile name
  603.   @email_save_in_sent_folder   INT           = NULL, -- 1 or 0
  604.   @cpu_poller_enabled          INT           = NULL  -- 1 or 0
  605. AS
  606. BEGIN
  607.   -- NOTE: We set all SQLServerAgent properties at one go for performance reasons.
  608.   -- NOTE: You cannot set the value of the properties msx_server_name, is_msx or
  609.   --       startup_account - they are all read only.
  610.  
  611.   DECLARE @res_valid_range           NVARCHAR(100)
  612.   DECLARE @existing_core_engine_mask INT
  613.  
  614.   SET NOCOUNT ON
  615.  
  616.   -- Remove any leading/trailing spaces from parameters
  617.   SELECT @errorlog_file     = LTRIM(RTRIM(@errorlog_file))
  618.   SELECT @error_recipient   = LTRIM(RTRIM(@error_recipient))
  619.   SELECT @local_host_server = LTRIM(RTRIM(@local_host_server))
  620.   SELECT @host_login_name   = LTRIM(RTRIM(@host_login_name))
  621.   SELECT @email_profile     = LTRIM(RTRIM(@email_profile))
  622.  
  623.   -- Make sure values (if supplied) are good
  624.   IF (@auto_start IS NOT NULL)
  625.   BEGIN
  626.     -- NOTE: When setting the the services start value, 2 == auto-start, 3 == Don't auto-start
  627.     SELECT @auto_start = CASE @auto_start
  628.                            WHEN 0 THEN 3
  629.                            WHEN 1 THEN 2
  630.                            ELSE 3 -- Assume non auto-start if passed a junk value
  631.                           END
  632.   END
  633.  
  634.   -- Non-SQLDMO exposed properties
  635.   IF ((@sqlserver_restart IS NOT NULL) AND (@sqlserver_restart <> 0))
  636.     SELECT @sqlserver_restart = 1
  637.  
  638.   IF (@jobhistory_max_rows IS NOT NULL)
  639.   BEGIN
  640.     SELECT @res_valid_range = FORMATMESSAGE(14207)
  641.     IF ((@jobhistory_max_rows < -1) OR (@jobhistory_max_rows = 0))
  642.     BEGIN
  643.       RAISERROR(14266, -1, -1, '@jobhistory_max_rows', @res_valid_range)
  644.       RETURN(1) -- Failure
  645.     END
  646.   END
  647.   ELSE
  648.   BEGIN
  649.     EXECUTE master.dbo.xp_regread N'HKEY_LOCAL_MACHINE',
  650.                                   N'SOFTWARE\Microsoft\MSSQLServer\SQLServerAgent',
  651.                                   N'JobHistoryMaxRows',
  652.                                    @jobhistory_max_rows OUTPUT,
  653.                                   N'no_output'
  654.     SELECT @jobhistory_max_rows = ISNULL(@jobhistory_max_rows, -1)
  655.   END
  656.  
  657.   IF (@jobhistory_max_rows_per_job IS NOT NULL)
  658.   BEGIN
  659.     IF (@jobhistory_max_rows = -1)
  660.       SELECT @jobhistory_max_rows_per_job = 0
  661.     ELSE
  662.     BEGIN
  663.       IF ((@jobhistory_max_rows_per_job < 1) OR (@jobhistory_max_rows_per_job > @jobhistory_max_rows))
  664.       BEGIN
  665.         SELECT @res_valid_range = N'1..' + CONVERT(NVARCHAR, @jobhistory_max_rows)
  666.         RAISERROR(14266, -1, -1, '@jobhistory_max_rows', @res_valid_range)
  667.         RETURN(1) -- Failure
  668.       END
  669.     END
  670.   END
  671.  
  672.   IF (@errorlogging_level IS NOT NULL) AND ((@errorlogging_level < 1) OR (@errorlogging_level > 7))
  673.   BEGIN
  674.     RAISERROR(14266, -1, -1, '@errorlogging_level', '1..7')
  675.     RETURN(1) -- Failure
  676.   END
  677.  
  678.   IF (@monitor_autostart IS NOT NULL) AND ((@monitor_autostart < 0) OR (@monitor_autostart > 1))
  679.   BEGIN
  680.     RAISERROR(14266, -1, -1, '@monitor_autostart', '0, 1')
  681.     RETURN(1) -- Failure
  682.   END
  683.  
  684.   IF (@job_shutdown_timeout IS NOT NULL) AND ((@job_shutdown_timeout < 5) OR (@job_shutdown_timeout > 600))
  685.   BEGIN
  686.     RAISERROR(14266, -1, -1, '@job_shutdown_timeout', '5..600')
  687.     RETURN(1) -- Failure
  688.   END
  689.  
  690.   IF (@regular_connections IS NOT NULL) AND ((@regular_connections < 0) OR (@regular_connections > 1))
  691.   BEGIN
  692.     RAISERROR(14266, -1, -1, '@regular_connections', '0, 1')
  693.     RETURN(1) -- Failure
  694.   END
  695.  
  696.   IF (@login_timeout IS NOT NULL) AND ((@login_timeout < 5) OR (@login_timeout > 45))
  697.   BEGIN
  698.     RAISERROR(14266, -1, -1, '@login_timeout', '5..45')
  699.     RETURN(1) -- Failure
  700.   END
  701.  
  702.   IF ((@idle_cpu_percent IS NOT NULL) AND ((@idle_cpu_percent < 1) OR (@idle_cpu_percent > 100)))
  703.   BEGIN
  704.     RAISERROR(14266, -1, -1, '@idle_cpu_percent', '10..100')
  705.     RETURN(1) -- Failure
  706.   END
  707.  
  708.   IF ((@idle_cpu_duration IS NOT NULL) AND ((@idle_cpu_duration < 20) OR (@idle_cpu_duration > 86400)))
  709.   BEGIN
  710.     RAISERROR(14266, -1, -1, '@idle_cpu_duration', '20..86400')
  711.     RETURN(1) -- Failure
  712.   END
  713.  
  714.   IF (@oem_errorlog IS NOT NULL) AND ((@oem_errorlog < 0) OR (@oem_errorlog > 1))
  715.   BEGIN
  716.     RAISERROR(14266, -1, -1, '@oem_errorlog', '0, 1')
  717.     RETURN(1) -- Failure
  718.   END
  719.  
  720.   IF (@sysadmin_only IS NOT NULL) AND ((@sysadmin_only < 0) OR (@sysadmin_only > 1))
  721.   BEGIN
  722.     RAISERROR(14266, -1, -1, '@sysadmin_only', '0, 1')
  723.     RETURN(1) -- Failure
  724.   END
  725.  
  726.   IF (@email_save_in_sent_folder IS NOT NULL) AND ((@email_save_in_sent_folder < 0) OR (@email_save_in_sent_folder > 1))
  727.   BEGIN
  728.     RAISERROR(14266, -1, -1, 'email_save_in_sent_folder', '0, 1')
  729.     RETURN(1) -- Failure
  730.   END
  731.  
  732.   IF (@cpu_poller_enabled IS NOT NULL) AND ((@cpu_poller_enabled < 0) OR (@cpu_poller_enabled > 1))
  733.   BEGIN
  734.     RAISERROR(14266, -1, -1, 'cpu_poller_enabled', '0, 1')
  735.     RETURN(1) -- Failure
  736.   END
  737.  
  738.   -- Write out the values
  739.   IF (@auto_start IS NOT NULL)
  740.   BEGIN
  741.     IF ((PLATFORM() & 0x1) = 0x1) -- NT
  742.       EXECUTE master.dbo.xp_regwrite N'HKEY_LOCAL_MACHINE',
  743.                                      N'SYSTEM\CurrentControlSet\Services\SQLServerAgent',
  744.                                      N'Start',
  745.                                      N'REG_DWORD',
  746.                                       @auto_start
  747.     ELSE
  748.       RAISERROR(14546, 16, 1, '@auto_start')
  749.   END
  750.  
  751.   -- Non-SQLDMO exposed properties
  752.   IF (@sqlserver_restart IS NOT NULL)
  753.     EXECUTE master.dbo.xp_regwrite N'HKEY_LOCAL_MACHINE',
  754.                                    N'SOFTWARE\Microsoft\MSSQLServer\SQLServerAgent',
  755.                                    N'RestartSQLServer',
  756.                                    N'REG_DWORD',
  757.                                     @sqlserver_restart
  758.   IF (@jobhistory_max_rows IS NOT NULL)
  759.     EXECUTE master.dbo.xp_regwrite N'HKEY_LOCAL_MACHINE',
  760.                                    N'SOFTWARE\Microsoft\MSSQLServer\SQLServerAgent',
  761.                                    N'JobHistoryMaxRows',
  762.                                    N'REG_DWORD',
  763.                                     @jobhistory_max_rows
  764.   IF (@jobhistory_max_rows_per_job IS NOT NULL)
  765.     EXECUTE master.dbo.xp_regwrite N'HKEY_LOCAL_MACHINE',
  766.                                    N'SOFTWARE\Microsoft\MSSQLServer\SQLServerAgent',
  767.                                    N'JobHistoryMaxRowsPerJob',
  768.                                    N'REG_DWORD',
  769.                                     @jobhistory_max_rows_per_job
  770.   IF (@errorlog_file IS NOT NULL)
  771.     EXECUTE master.dbo.xp_regwrite N'HKEY_LOCAL_MACHINE',
  772.                                    N'SOFTWARE\Microsoft\MSSQLServer\SQLServerAgent',
  773.                                    N'ErrorLogFile',
  774.                                    N'REG_SZ',
  775.                                     @errorlog_file
  776.   IF (@errorlogging_level IS NOT NULL)
  777.     EXECUTE master.dbo.xp_regwrite N'HKEY_LOCAL_MACHINE',
  778.                                    N'SOFTWARE\Microsoft\MSSQLServer\SQLServerAgent',
  779.                                    N'ErrorLoggingLevel',
  780.                                    N'REG_DWORD',
  781.                                     @errorlogging_level
  782.   IF (@error_recipient IS NOT NULL)
  783.     EXECUTE master.dbo.xp_regwrite N'HKEY_LOCAL_MACHINE',
  784.                                    N'SOFTWARE\Microsoft\MSSQLServer\SQLServerAgent',
  785.                                    N'ErrorMonitor',
  786.                                    N'REG_SZ',
  787.                                     @error_recipient
  788.   IF (@monitor_autostart IS NOT NULL)
  789.     EXECUTE master.dbo.xp_regwrite N'HKEY_LOCAL_MACHINE',
  790.                                    N'SOFTWARE\Microsoft\MSSQLServer\SQLServerAgent',
  791.                                    N'MonitorAutoStart',
  792.                                    N'REG_DWORD',
  793.                                     @monitor_autostart
  794.   IF (@local_host_server IS NOT NULL)
  795.     EXECUTE master.dbo.xp_regwrite N'HKEY_LOCAL_MACHINE',
  796.                                    N'SOFTWARE\Microsoft\MSSQLServer\SQLServerAgent',
  797.                                    N'ServerHost',
  798.                                    N'REG_SZ',
  799.                                     @local_host_server
  800.   IF (@job_shutdown_timeout IS NOT NULL)
  801.     EXECUTE master.dbo.xp_regwrite N'HKEY_LOCAL_MACHINE',
  802.                                    N'SOFTWARE\Microsoft\MSSQLServer\SQLServerAgent',
  803.                                    N'JobShutdownTimeout',
  804.                                    N'REG_DWORD',
  805.                                     @job_shutdown_timeout
  806.   IF (@cmdexec_account IS NOT NULL)
  807.     EXECUTE master.dbo.xp_regwrite N'HKEY_LOCAL_MACHINE',
  808.                                    N'SOFTWARE\Microsoft\MSSQLServer\SQLServerAgent',
  809.                                    N'CmdExecAccount',
  810.                                    N'REG_BINARY',
  811.                                     @cmdexec_account
  812.   IF (@regular_connections IS NOT NULL)
  813.     EXECUTE master.dbo.xp_regwrite N'HKEY_LOCAL_MACHINE',
  814.                                    N'SOFTWARE\Microsoft\MSSQLServer\SQLServerAgent',
  815.                                    N'RegularConnections',
  816.                                    N'REG_DWORD',
  817.                                     @regular_connections
  818.   IF (@host_login_name IS NOT NULL)
  819.     EXECUTE master.dbo.xp_regwrite N'HKEY_LOCAL_MACHINE',
  820.                                    N'SOFTWARE\Microsoft\MSSQLServer\SQLServerAgent',
  821.                                    N'HostLoginID',
  822.                                    N'REG_SZ',
  823.                                     @host_login_name
  824.   IF (@host_login_password IS NOT NULL)
  825.     EXECUTE master.dbo.xp_regwrite N'HKEY_LOCAL_MACHINE',
  826.                                    N'SOFTWARE\Microsoft\MSSQLServer\SQLServerAgent',
  827.                                    N'HostPassword',
  828.                                    N'REG_BINARY',
  829.                                     @host_login_password
  830.   IF (@login_timeout IS NOT NULL)
  831.     EXECUTE master.dbo.xp_regwrite N'HKEY_LOCAL_MACHINE',
  832.                                    N'SOFTWARE\Microsoft\MSSQLServer\SQLServerAgent',
  833.                                    N'LoginTimeout',
  834.                                    N'REG_DWORD',
  835.                                     @login_timeout
  836.   IF (@idle_cpu_percent IS NOT NULL)
  837.     EXECUTE master.dbo.xp_regwrite N'HKEY_LOCAL_MACHINE',
  838.                                    N'SOFTWARE\Microsoft\MSSQLServer\SQLServerAgent',
  839.                                    N'IdleCPUPercent',
  840.                                    N'REG_DWORD',
  841.                                     @idle_cpu_percent
  842.   IF (@idle_cpu_duration IS NOT NULL)
  843.     EXECUTE master.dbo.xp_regwrite N'HKEY_LOCAL_MACHINE',
  844.                                    N'SOFTWARE\Microsoft\MSSQLServer\SQLServerAgent',
  845.                                    N'IdleCPUDuration',
  846.                                    N'REG_DWORD',
  847.                                     @idle_cpu_duration
  848.   IF (@oem_errorlog IS NOT NULL)
  849.     EXECUTE master.dbo.xp_regwrite N'HKEY_LOCAL_MACHINE',
  850.                                    N'SOFTWARE\Microsoft\MSSQLServer\SQLServerAgent',
  851.                                    N'OemErrorLog',
  852.                                    N'REG_DWORD',
  853.                                     @oem_errorlog
  854.   IF (@sysadmin_only IS NOT NULL)
  855.     EXECUTE master.dbo.xp_regwrite N'HKEY_LOCAL_MACHINE',
  856.                                    N'SOFTWARE\Microsoft\MSSQLServer\SQLServerAgent',
  857.                                    N'SysAdminOnly',
  858.                                    N'REG_DWORD',
  859.                                     @sysadmin_only
  860.   IF (@email_profile IS NOT NULL)
  861.     EXECUTE master.dbo.xp_regwrite N'HKEY_LOCAL_MACHINE',
  862.                                    N'SOFTWARE\Microsoft\MSSQLServer\SQLServerAgent',
  863.                                    N'EmailProfile',
  864.                                    N'REG_SZ',
  865.                                     @email_profile
  866.   IF (@email_save_in_sent_folder IS NOT NULL)
  867.     EXECUTE master.dbo.xp_regwrite N'HKEY_LOCAL_MACHINE',
  868.                                    N'SOFTWARE\Microsoft\MSSQLServer\SQLServerAgent',
  869.                                    N'EmailSaveSent',
  870.                                    N'REG_DWORD',
  871.                                     @email_save_in_sent_folder
  872.   IF (@cpu_poller_enabled IS NOT NULL)
  873.   BEGIN
  874.     EXECUTE master.dbo.xp_regread N'HKEY_LOCAL_MACHINE',
  875.                                   N'SOFTWARE\Microsoft\MSSQLServer\SQLServerAgent',
  876.                                   N'CoreEngineMask',
  877.                                    @existing_core_engine_mask OUTPUT,
  878.                                   N'no_output'
  879.     IF ((@existing_core_engine_mask IS NOT NULL) OR (@cpu_poller_enabled = 1))
  880.     BEGIN
  881.       IF (@cpu_poller_enabled = 1)
  882.         SELECT @cpu_poller_enabled = (ISNULL(@existing_core_engine_mask, 0) & ~32)
  883.       ELSE
  884.         SELECT @cpu_poller_enabled = (ISNULL(@existing_core_engine_mask, 0) | 32)
  885.  
  886.       IF ((@existing_core_engine_mask IS NOT NULL) AND (@cpu_poller_enabled = 32))
  887.         EXECUTE master.dbo.xp_regdeletevalue N'HKEY_LOCAL_MACHINE',
  888.                                              N'SOFTWARE\Microsoft\MSSQLServer\SQLServerAgent',
  889.                                              N'CoreEngineMask'
  890.       ELSE
  891.         EXECUTE master.dbo.xp_regwrite N'HKEY_LOCAL_MACHINE',
  892.                                        N'SOFTWARE\Microsoft\MSSQLServer\SQLServerAgent',
  893.                                        N'CoreEngineMask',
  894.                                        N'REG_DWORD',
  895.                                         @cpu_poller_enabled
  896.     END
  897.   END
  898.  
  899.   RETURN(0) -- Success
  900. END
  901. go
  902.  
  903. /**************************************************************/
  904. /* SP_MSX_ENLIST                                              */
  905. /**************************************************************/
  906.  
  907. PRINT ''
  908. PRINT 'Creating procedure sp_msx_enlist...'
  909. go
  910. IF (EXISTS (SELECT *
  911.             FROM msdb.dbo.sysobjects
  912.             WHERE (name = 'sp_msx_enlist')
  913.               AND (type = 'P')))
  914.   DROP PROCEDURE sp_msx_enlist
  915. go
  916. CREATE PROCEDURE sp_msx_enlist
  917.   @msx_server_name NVARCHAR(30),
  918.   @location        NVARCHAR(100) = NULL, -- The procedure will supply a default
  919.   @ping_server     BIT = 1               -- Set to 0 to skip the MSX ping test
  920. AS
  921. BEGIN
  922.   DECLARE @current_msx_server   NVARCHAR(30)
  923.   DECLARE @local_machine_name   NVARCHAR(30)
  924.   DECLARE @retval               INT
  925.   DECLARE @time_zone_adjustment INT
  926.   DECLARE @local_time           NVARCHAR(100)
  927.   DECLARE @nt_user              NVARCHAR(100)
  928.   DECLARE @poll_interval        INT
  929.  
  930.   SET NOCOUNT ON
  931.  
  932.   -- Only a sysadmin can do this
  933.   IF (ISNULL(IS_SRVROLEMEMBER(N'sysadmin'), 0) <> 1)
  934.   BEGIN
  935.     RAISERROR(15003, 16, 1, N'sysadmin')
  936.     RETURN(1) -- Failure
  937.   END
  938.  
  939.   -- Only an NT server can be enlisted
  940.   IF ((PLATFORM() & 0x1) <> 0x1) -- NT
  941.   BEGIN
  942.     RAISERROR(14540, -1, 1)
  943.     RETURN(1) -- Failure
  944.   END
  945.  
  946.   -- Only SBS, Standard, or Enterprise editions of SQL Server can be enlisted
  947.   IF ((PLATFORM() & 0x100) = 0x100) -- Desktop package
  948.   BEGIN
  949.     RAISERROR(14539, -1, -1)
  950.     RETURN(1) -- Failure
  951.   END
  952.  
  953.   -- Remove any leading/trailing spaces from parameters
  954.   SELECT @msx_server_name = LTRIM(RTRIM(@msx_server_name))
  955.   SELECT @location        = LTRIM(RTRIM(@location))
  956.  
  957.   -- Turn [nullable] empty string parameters into NULLs
  958.   IF (@location = N'') SELECT @location = NULL
  959.  
  960.   -- Change to MSX server name to upper-case since it's a machine name
  961.   SELECT @msx_server_name = UPPER(@msx_server_name)
  962.  
  963.   SELECT @retval = 0
  964.  
  965.   -- Get the values that we'll need for the [re]enlistment operation (except the local time
  966.   -- which we get right before we call xp_msx_enlist to that it's as accurate as possible)
  967.   SELECT @nt_user = ISNULL(NT_CLIENT(), ISNULL(SUSER_SNAME(), FORMATMESSAGE(14205)))
  968.   EXECUTE master.dbo.xp_regread N'HKEY_LOCAL_MACHINE',
  969.                                 N'SYSTEM\CurrentControlSet\Control\TimeZoneInformation',
  970.                                 N'Bias',
  971.                                  @time_zone_adjustment OUTPUT,
  972.                                 N'no_output'
  973.   IF ((PLATFORM() & 0x1) = 0x1) -- NT
  974.     SELECT @time_zone_adjustment = -ISNULL(@time_zone_adjustment, 0)
  975.   ELSE
  976.     SELECT @time_zone_adjustment = -CONVERT(INT, CONVERT(BINARY(2), ISNULL(@time_zone_adjustment, 0)))
  977.   
  978.   EXECUTE master.dbo.xp_regread N'HKEY_LOCAL_MACHINE',
  979.                                 N'SOFTWARE\Microsoft\MSSQLServer\SQLServerAgent',
  980.                                 N'MSXPollInterval',
  981.                                  @poll_interval OUTPUT,
  982.                                 N'no_output'
  983.   SELECT @poll_interval = ISNULL(@poll_interval, 60) -- This should be the same as DEF_REG_MSX_POLL_INTERVAL
  984.   EXECUTE master.dbo.xp_regread N'HKEY_LOCAL_MACHINE',
  985.                                 N'SOFTWARE\Microsoft\MSSQLServer\SQLServerAgent',
  986.                                 N'MSXServerName',
  987.                                  @current_msx_server OUTPUT,
  988.                                 N'no_output'
  989.   SELECT @current_msx_server = LTRIM(RTRIM(@current_msx_server))
  990.   EXECUTE @retval = master.dbo.xp_getnetname @local_machine_name OUTPUT
  991.   IF (@retval <> 0)
  992.     RETURN(1) -- Failure
  993.  
  994.   -- Check if this machine is an MSX (and therefore cannot be enlisted into another MSX)
  995.   IF (EXISTS (SELECT *
  996.               FROM msdb.dbo.systargetservers))
  997.   BEGIN
  998.     RAISERROR(14299, -1, -1, @local_machine_name)
  999.     RETURN(1) -- Failure
  1000.   END
  1001.  
  1002.   -- Check if the MSX supplied is the same as the local machine (this is not allowed)
  1003.   IF (UPPER(@local_machine_name) = UPPER(@msx_server_name))
  1004.   BEGIN
  1005.     RAISERROR(14297, -1, -1)
  1006.     RETURN(1) -- Failure
  1007.   END
  1008.  
  1009.   -- Check if MSDB has be re-installed since we enlisted
  1010.   IF (@current_msx_server IS NOT NULL) AND
  1011.      (NOT EXISTS (SELECT *
  1012.                   FROM msdb.dbo.sqlagent_info
  1013.                   WHERE (attribute = 'DateEnlisted')))
  1014.   BEGIN
  1015.     -- User is tring to [re]enlist after a re-install, so we have to forcefully defect before
  1016.     -- we can fully enlist again
  1017.     EXECUTE msdb.dbo.sp_msx_defect @forced_defection = 1
  1018.     SELECT @current_msx_server = NULL
  1019.   END  
  1020.  
  1021.   -- Check if we are already enlisted, in which case we re-enlist
  1022.   IF ((@current_msx_server IS NOT NULL) AND (@current_msx_server <> N''))
  1023.   BEGIN
  1024.     IF (UPPER(@current_msx_server) = UPPER(@msx_server_name))
  1025.     BEGIN
  1026.       -- Update the [existing] enlistment
  1027.       SELECT @local_time = CONVERT(NVARCHAR, GETDATE(), 112) + N' ' + CONVERT(NVARCHAR, GETDATE(), 108)
  1028.       EXECUTE @retval = master.dbo.xp_msx_enlist 2, @msx_server_name, @nt_user, @location, @time_zone_adjustment, @local_time, @poll_interval
  1029.       RETURN(@retval) -- 0 means success
  1030.     END
  1031.     ELSE
  1032.     BEGIN
  1033.       RAISERROR(14296, -1, -1, @current_msx_server)
  1034.       RETURN(1) -- Failure
  1035.     END
  1036.   END
  1037.  
  1038.   -- If we get this far then we're dealing with a new enlistment...
  1039.  
  1040.   -- Check if the MSX supplied exists on the network
  1041.   IF (@ping_server = 1)
  1042.   BEGIN
  1043.     DECLARE @msx_machine_name NVARCHAR (30)
  1044.     DECLARE @char_index       INT
  1045.  
  1046.     SELECT @char_index = CHARINDEX (N'\', @msx_server_name)
  1047.     IF (@char_index > 0)
  1048.     BEGIN
  1049.       SELECT @msx_machine_name = LEFT (@msx_server_name, @char_index - 1)
  1050.     END
  1051.     ELSE
  1052.     BEGIN
  1053.       SELECT @msx_machine_name = @msx_server_name
  1054.     END
  1055.  
  1056.     IF ((PLATFORM() & 0x2) = 0x2) -- Win9x
  1057.     BEGIN
  1058.       EXECUTE(N'CREATE TABLE #output (output NVARCHAR(1024) COLLATE database_default)
  1059.                 SET NOCOUNT ON
  1060.                 INSERT INTO #output
  1061.                 EXECUTE master.dbo.xp_cmdshell N''net view \\' + @msx_machine_name + N'''
  1062.                 IF (EXISTS (SELECT *
  1063.                             FROM #output
  1064.                             WHERE (output LIKE N''% 53%'')))
  1065.                    RAISERROR(14262, -1, -1, N''@msx_server_name'', N''' + @msx_machine_name + N''') WITH SETERROR')
  1066.       IF (@@error <> 0)
  1067.         RETURN(1) -- Failure
  1068.     END
  1069.     ELSE
  1070.     BEGIN
  1071.       EXECUTE(N'DECLARE @retval INT
  1072.                 SET NOCOUNT ON
  1073.                 EXECUTE @retval = master.dbo.xp_cmdshell N''net view \\' + @msx_machine_name + N' > nul'', no_output
  1074.                 IF (@retval <> 0)
  1075.                   RAISERROR(14262, -1, -1, N''@msx_server_name'', N''' + @msx_machine_name + N''') WITH SETERROR')
  1076.       IF (@@error <> 0)
  1077.         RETURN(1) -- Failure
  1078.     END
  1079.   END
  1080.  
  1081.   -- If no location is supplied, generate one (such as we can)
  1082.   IF (@location IS NULL)
  1083.     EXECUTE msdb.dbo.sp_generate_server_description @location OUTPUT
  1084.  
  1085.   SELECT @local_time = CONVERT(NVARCHAR, GETDATE(), 112) + ' ' + CONVERT(NVARCHAR, GETDATE(), 108)
  1086.   EXECUTE @retval = master.dbo.xp_msx_enlist 0, @msx_server_name, @nt_user, @location, @time_zone_adjustment, @local_time, @poll_interval
  1087.  
  1088.   IF (@retval = 0)
  1089.   BEGIN
  1090.     EXECUTE master.dbo.xp_regwrite N'HKEY_LOCAL_MACHINE',
  1091.                                    N'SOFTWARE\Microsoft\MSSQLServer\SQLServerAgent',
  1092.                                    N'MSXServerName',
  1093.                                    N'REG_SZ',
  1094.                                     @msx_server_name
  1095.  
  1096.     IF (@current_msx_server IS NOT NULL)
  1097.       RAISERROR(14228, 0, 1, @current_msx_server, @msx_server_name)
  1098.     ELSE
  1099.       RAISERROR(14229, 0, 1, @msx_server_name)
  1100.  
  1101.     -- Add entry to sqlagent_info
  1102.     INSERT INTO msdb.dbo.sqlagent_info (attribute, value) VALUES ('DateEnlisted', CONVERT(VARCHAR(10), GETDATE(), 112))
  1103.   END
  1104.  
  1105.   RETURN(@retval) -- 0 means success
  1106. END
  1107. go
  1108.  
  1109.  
  1110. /**************************************************************/
  1111. /* SP_GET_COMPOSITE_JOB_INFO                                  */
  1112. /**************************************************************/
  1113.  
  1114. PRINT ''
  1115. PRINT 'Creating procedure sp_get_composite_job_info...'
  1116. go
  1117. IF (EXISTS (SELECT *
  1118.             FROM msdb.dbo.sysobjects
  1119.             WHERE (name = N'sp_get_composite_job_info')
  1120.               AND (type = 'P')))
  1121.   DROP PROCEDURE sp_get_composite_job_info
  1122. go
  1123. CREATE PROCEDURE sp_get_composite_job_info
  1124.   @job_id             UNIQUEIDENTIFIER = NULL,
  1125.   @job_type           VARCHAR(12)      = NULL,  -- LOCAL or MULTI-SERVER
  1126.   @owner_login_name   sysname          = NULL,
  1127.   @subsystem          NVARCHAR(40)     = NULL,
  1128.   @category_id        INT              = NULL,
  1129.   @enabled            TINYINT          = NULL,
  1130.   @execution_status   INT              = NULL,  -- 0 = Not idle or suspended, 1 = Executing, 2 = Waiting For Thread, 3 = Between Retries, 4 = Idle, 5 = Suspended, [6 = WaitingForStepToFinish], 7 = PerformingCompletionActions
  1131.   @date_comparator    CHAR(1)          = NULL,  -- >, < or =
  1132.   @date_created       DATETIME         = NULL,
  1133.   @date_last_modified DATETIME         = NULL,
  1134.   @description        NVARCHAR(512)    = NULL   -- We do a LIKE on this so it can include wildcards
  1135. AS
  1136. BEGIN
  1137.   DECLARE @is_sysadmin INT
  1138.   DECLARE @job_owner   sysname
  1139.  
  1140.   SET NOCOUNT ON
  1141.  
  1142.   -- By 'composite' we mean a combination of sysjobs and xp_sqlagent_enum_jobs data.
  1143.   -- This proc should only ever be called by sp_help_job, so we don't verify the
  1144.   -- parameters (sp_help_job has already done this).
  1145.  
  1146.   -- Step 1: Create intermediate work tables
  1147.   CREATE TABLE #job_execution_state (job_id                  UNIQUEIDENTIFIER NOT NULL,
  1148.                                      date_started            INT              NOT NULL,
  1149.                                      time_started            INT              NOT NULL,
  1150.                                      execution_job_status    INT              NOT NULL,
  1151.                                      execution_step_id       INT              NULL,
  1152.                                      execution_step_name     sysname          NULL,
  1153.                                      execution_retry_attempt INT              NOT NULL,
  1154.                                      next_run_date           INT              NOT NULL,
  1155.                                      next_run_time           INT              NOT NULL,
  1156.                                      next_run_schedule_id    INT              NOT NULL)
  1157.   CREATE TABLE #filtered_jobs (job_id                   UNIQUEIDENTIFIER NOT NULL,
  1158.                                date_created             DATETIME         NOT NULL,
  1159.                                date_last_modified       DATETIME         NOT NULL,
  1160.                                current_execution_status INT              NULL,
  1161.                                current_execution_step   sysname          NULL,
  1162.                                current_retry_attempt    INT              NULL,
  1163.                                last_run_date            INT              NOT NULL,
  1164.                                last_run_time            INT              NOT NULL,
  1165.                                last_run_outcome         INT              NOT NULL,
  1166.                                next_run_date            INT              NULL,
  1167.                                next_run_time            INT              NULL,
  1168.                                next_run_schedule_id     INT              NULL,
  1169.                                type                     INT              NOT NULL)
  1170.   CREATE TABLE #xp_results (job_id                UNIQUEIDENTIFIER NOT NULL,
  1171.                             last_run_date         INT              NOT NULL,
  1172.                             last_run_time         INT              NOT NULL,
  1173.                             next_run_date         INT              NOT NULL,
  1174.                             next_run_time         INT              NOT NULL,
  1175.                             next_run_schedule_id  INT              NOT NULL,
  1176.                             requested_to_run      INT              NOT NULL, -- BOOL
  1177.                             request_source        INT              NOT NULL,
  1178.                             request_source_id     sysname          NULL,
  1179.                             running               INT              NOT NULL, -- BOOL
  1180.                             current_step          INT              NOT NULL,
  1181.                             current_retry_attempt INT              NOT NULL,
  1182.                             job_state             INT              NOT NULL)
  1183.  
  1184.   -- Step 2: Capture job execution information (for local jobs only since that's all SQLServerAgent caches)
  1185.   SELECT @is_sysadmin = ISNULL(IS_SRVROLEMEMBER(N'sysadmin'), 0)
  1186.   SELECT @job_owner = SUSER_SNAME()
  1187.  
  1188.   
  1189.   IF ((@@microsoftversion / 0x01000000) >= 8) -- SQL Server 8.0 or greater
  1190.     INSERT INTO #xp_results
  1191.     EXECUTE master.dbo.xp_sqlagent_enum_jobs @is_sysadmin, @job_owner, @job_id
  1192.   ELSE
  1193.     INSERT INTO #xp_results
  1194.     EXECUTE master.dbo.xp_sqlagent_enum_jobs @is_sysadmin, @job_owner
  1195.  
  1196.   INSERT INTO #job_execution_state
  1197.   SELECT xpr.job_id,
  1198.          xpr.last_run_date,
  1199.          xpr.last_run_time,
  1200.          xpr.job_state,
  1201.          sjs.step_id,
  1202.          sjs.step_name,
  1203.          xpr.current_retry_attempt,
  1204.          xpr.next_run_date,
  1205.          xpr.next_run_time,
  1206.          xpr.next_run_schedule_id
  1207.   FROM #xp_results                          xpr
  1208.        LEFT OUTER JOIN msdb.dbo.sysjobsteps sjs ON ((xpr.job_id = sjs.job_id) AND (xpr.current_step = sjs.step_id)),
  1209.        msdb.dbo.sysjobs_view                sjv
  1210.   WHERE (sjv.job_id = xpr.job_id)
  1211.  
  1212.   -- Step 3: Filter on everything but dates and job_type
  1213.   IF ((@subsystem        IS NULL) AND
  1214.       (@owner_login_name IS NULL) AND
  1215.       (@enabled          IS NULL) AND
  1216.       (@category_id      IS NULL) AND
  1217.       (@execution_status IS NULL) AND
  1218.       (@description      IS NULL) AND
  1219.       (@job_id           IS NULL))
  1220.   BEGIN
  1221.     -- Optimize for the frequently used case...
  1222.     INSERT INTO #filtered_jobs
  1223.     SELECT sjv.job_id,
  1224.            sjv.date_created,
  1225.            sjv.date_modified,
  1226.            ISNULL(jes.execution_job_status, 4), -- Will be NULL if the job is non-local or is not in #job_execution_state (NOTE: 4 = STATE_IDLE)
  1227.            CASE ISNULL(jes.execution_step_id, 0)
  1228.              WHEN 0 THEN NULL                   -- Will be NULL if the job is non-local or is not in #job_execution_state
  1229.              ELSE CONVERT(NVARCHAR, jes.execution_step_id) + N' (' + jes.execution_step_name + N')'
  1230.            END,
  1231.            jes.execution_retry_attempt,         -- Will be NULL if the job is non-local or is not in #job_execution_state
  1232.            0,  -- last_run_date placeholder    (we'll fix it up in step 3.3)
  1233.            0,  -- last_run_time placeholder    (we'll fix it up in step 3.3)
  1234.            5,  -- last_run_outcome placeholder (we'll fix it up in step 3.3 - NOTE: We use 5 just in case there are no jobservers for the job)
  1235.            jes.next_run_date,                   -- Will be NULL if the job is non-local or is not in #job_execution_state
  1236.            jes.next_run_time,                   -- Will be NULL if the job is non-local or is not in #job_execution_state
  1237.            jes.next_run_schedule_id,            -- Will be NULL if the job is non-local or is not in #job_execution_state
  1238.            0   -- type placeholder             (we'll fix it up in step 3.4)
  1239.     FROM msdb.dbo.sysjobs_view                sjv
  1240.          LEFT OUTER JOIN #job_execution_state jes ON (sjv.job_id = jes.job_id)
  1241.   END
  1242.   ELSE
  1243.   BEGIN
  1244.     INSERT INTO #filtered_jobs
  1245.     SELECT DISTINCT
  1246.            sjv.job_id,
  1247.            sjv.date_created,
  1248.            sjv.date_modified,
  1249.            ISNULL(jes.execution_job_status, 4), -- Will be NULL if the job is non-local or is not in #job_execution_state (NOTE: 4 = STATE_IDLE)
  1250.            CASE ISNULL(jes.execution_step_id, 0)
  1251.              WHEN 0 THEN NULL                   -- Will be NULL if the job is non-local or is not in #job_execution_state
  1252.              ELSE CONVERT(NVARCHAR, jes.execution_step_id) + N' (' + jes.execution_step_name + N')'
  1253.            END,
  1254.            jes.execution_retry_attempt,         -- Will be NULL if the job is non-local or is not in #job_execution_state
  1255.            0,  -- last_run_date placeholder    (we'll fix it up in step 3.3)
  1256.            0,  -- last_run_time placeholder    (we'll fix it up in step 3.3)
  1257.            5,  -- last_run_outcome placeholder (we'll fix it up in step 3.3 - NOTE: We use 5 just in case there are no jobservers for the job)
  1258.            jes.next_run_date,                   -- Will be NULL if the job is non-local or is not in #job_execution_state
  1259.            jes.next_run_time,                   -- Will be NULL if the job is non-local or is not in #job_execution_state
  1260.            jes.next_run_schedule_id,            -- Will be NULL if the job is non-local or is not in #job_execution_state
  1261.            0   -- type placeholder             (we'll fix it up in step 3.4)
  1262.     FROM msdb.dbo.sysjobs_view                sjv
  1263.          LEFT OUTER JOIN #job_execution_state jes ON (sjv.job_id = jes.job_id)
  1264.          LEFT OUTER JOIN msdb.dbo.sysjobsteps sjs ON (sjv.job_id = sjs.job_id)
  1265.     WHERE ((@subsystem        IS NULL) OR (sjs.subsystem            = @subsystem))
  1266.       AND ((@owner_login_name IS NULL) OR (sjv.owner_sid            = SUSER_SID(@owner_login_name)))
  1267.       AND ((@enabled          IS NULL) OR (sjv.enabled              = @enabled))
  1268.       AND ((@category_id      IS NULL) OR (sjv.category_id          = @category_id))
  1269.       AND ((@execution_status IS NULL) OR ((@execution_status > 0) AND (jes.execution_job_status = @execution_status)) 
  1270.                                        OR ((@execution_status = 0) AND (jes.execution_job_status <> 4) AND (jes.execution_job_status <> 5)))
  1271.       AND ((@description      IS NULL) OR (sjv.description       LIKE @description))
  1272.       AND ((@job_id           IS NULL) OR (sjv.job_id               = @job_id))
  1273.   END
  1274.  
  1275.   -- Step 3.1: Change the execution status of non-local jobs from 'Idle' to 'Unknown'
  1276.   UPDATE #filtered_jobs
  1277.   SET current_execution_status = NULL
  1278.   WHERE (current_execution_status = 4)
  1279.     AND (job_id IN (SELECT job_id
  1280.                     FROM msdb.dbo.sysjobservers
  1281.                     WHERE (server_id <> 0)))
  1282.  
  1283.   -- Step 3.2: Check that if the user asked to see idle jobs that we still have some.
  1284.   --           If we don't have any then the query should return no rows.
  1285.   IF (@execution_status = 4) AND
  1286.      (NOT EXISTS (SELECT *
  1287.                   FROM #filtered_jobs
  1288.                   WHERE (current_execution_status = 4)))
  1289.   BEGIN
  1290.     TRUNCATE TABLE #filtered_jobs
  1291.   END
  1292.  
  1293.   -- Step 3.3: Populate the last run date/time/outcome [this is a little tricky since for
  1294.   --           multi-server jobs there are multiple last run details in sysjobservers, so
  1295.   --           we simply choose the most recent].
  1296.   IF (EXISTS (SELECT *
  1297.               FROM msdb.dbo.systargetservers))
  1298.   BEGIN
  1299.     UPDATE #filtered_jobs
  1300.     SET last_run_date = sjs.last_run_date,
  1301.         last_run_time = sjs.last_run_time,
  1302.         last_run_outcome = sjs.last_run_outcome
  1303.     FROM #filtered_jobs         fj,
  1304.          msdb.dbo.sysjobservers sjs
  1305.     WHERE (CONVERT(FLOAT, sjs.last_run_date) * 1000000) + sjs.last_run_time =
  1306.            (SELECT MAX((CONVERT(FLOAT, last_run_date) * 1000000) + last_run_time)
  1307.             FROM msdb.dbo.sysjobservers
  1308.             WHERE (job_id = sjs.job_id))
  1309.       AND (fj.job_id = sjs.job_id)
  1310.   END
  1311.   ELSE
  1312.   BEGIN
  1313.     UPDATE #filtered_jobs
  1314.     SET last_run_date = sjs.last_run_date,
  1315.         last_run_time = sjs.last_run_time,
  1316.         last_run_outcome = sjs.last_run_outcome
  1317.     FROM #filtered_jobs         fj,
  1318.          msdb.dbo.sysjobservers sjs
  1319.     WHERE (fj.job_id = sjs.job_id)
  1320.   END
  1321.  
  1322.   -- Step 3.4 : Set the type of the job to local (1) or multi-server (2)
  1323.   --            NOTE: If the job has no jobservers then it wil have a type of 0 meaning
  1324.   --                  unknown.  This is marginally inconsistent with the behaviour of
  1325.   --                  defaulting the category of a new job to [Uncategorized (Local)], but
  1326.   --                  prevents incompletely defined jobs from erroneously showing up as valid
  1327.   --                  local jobs.
  1328.   UPDATE #filtered_jobs
  1329.   SET type = 1 -- LOCAL
  1330.   FROM #filtered_jobs         fj,
  1331.        msdb.dbo.sysjobservers sjs
  1332.   WHERE (fj.job_id = sjs.job_id)
  1333.     AND (server_id = 0)
  1334.   UPDATE #filtered_jobs
  1335.   SET type = 2 -- MULTI-SERVER
  1336.   FROM #filtered_jobs         fj,
  1337.        msdb.dbo.sysjobservers sjs
  1338.   WHERE (fj.job_id = sjs.job_id)
  1339.     AND (server_id <> 0)
  1340.  
  1341.   -- Step 4: Filter on job_type
  1342.   IF (@job_type IS NOT NULL)
  1343.   BEGIN
  1344.     IF (UPPER(@job_type) = 'LOCAL')
  1345.       DELETE FROM #filtered_jobs
  1346.       WHERE (type <> 1) -- IE. Delete all the non-local jobs
  1347.     IF (UPPER(@job_type) = 'MULTI-SERVER')
  1348.       DELETE FROM #filtered_jobs
  1349.       WHERE (type <> 2) -- IE. Delete all the non-multi-server jobs
  1350.   END
  1351.  
  1352.   -- Step 5: Filter on dates
  1353.   IF (@date_comparator IS NOT NULL)
  1354.   BEGIN
  1355.     IF (@date_created IS NOT NULL)
  1356.     BEGIN
  1357.       IF (@date_comparator = '=')
  1358.         DELETE FROM #filtered_jobs WHERE (date_created <> @date_created)
  1359.       IF (@date_comparator = '>')
  1360.         DELETE FROM #filtered_jobs WHERE (date_created <= @date_created)
  1361.       IF (@date_comparator = '<')
  1362.         DELETE FROM #filtered_jobs WHERE (date_created >= @date_created)
  1363.     END
  1364.     IF (@date_last_modified IS NOT NULL)
  1365.     BEGIN
  1366.       IF (@date_comparator = '=')
  1367.         DELETE FROM #filtered_jobs WHERE (date_last_modified <> @date_last_modified)
  1368.       IF (@date_comparator = '>')
  1369.         DELETE FROM #filtered_jobs WHERE (date_last_modified <= @date_last_modified)
  1370.       IF (@date_comparator = '<')
  1371.         DELETE FROM #filtered_jobs WHERE (date_last_modified >= @date_last_modified)
  1372.     END
  1373.   END
  1374.  
  1375.   -- Return the result set (NOTE: No filtering occurs here)
  1376.   SELECT sjv.job_id,
  1377.          sjv.originating_server,
  1378.          sjv.name,
  1379.          sjv.enabled,
  1380.          sjv.description,
  1381.          sjv.start_step_id,
  1382.          category = ISNULL(sc.name, FORMATMESSAGE(14205)),
  1383.          owner = SUSER_SNAME(sjv.owner_sid),
  1384.          sjv.notify_level_eventlog,
  1385.          sjv.notify_level_email,
  1386.          sjv.notify_level_netsend,
  1387.          sjv.notify_level_page,
  1388.          notify_email_operator   = ISNULL(so1.name, FORMATMESSAGE(14205)),
  1389.          notify_netsend_operator = ISNULL(so2.name, FORMATMESSAGE(14205)),
  1390.          notify_page_operator    = ISNULL(so3.name, FORMATMESSAGE(14205)),
  1391.          sjv.delete_level,
  1392.          sjv.date_created,
  1393.          sjv.date_modified,
  1394.          sjv.version_number,
  1395.          fj.last_run_date,
  1396.          fj.last_run_time,
  1397.          fj.last_run_outcome,
  1398.          next_run_date = ISNULL(fj.next_run_date, 0),                                 -- This column will be NULL if the job is non-local
  1399.          next_run_time = ISNULL(fj.next_run_time, 0),                                 -- This column will be NULL if the job is non-local
  1400.          next_run_schedule_id = ISNULL(fj.next_run_schedule_id, 0),                   -- This column will be NULL if the job is non-local
  1401.          current_execution_status = ISNULL(fj.current_execution_status, 0),           -- This column will be NULL if the job is non-local
  1402.          current_execution_step = ISNULL(fj.current_execution_step, N'0 ' + FORMATMESSAGE(14205)), -- This column will be NULL if the job is non-local
  1403.          current_retry_attempt = ISNULL(fj.current_retry_attempt, 0),                 -- This column will be NULL if the job is non-local
  1404.          has_step = (SELECT COUNT(*) 
  1405.                      FROM msdb.dbo.sysjobsteps sjst
  1406.                      WHERE (sjst.job_id = sjv.job_id)),
  1407.          has_schedule = (SELECT COUNT(*) 
  1408.                          FROM msdb.dbo.sysjobschedules sjsch 
  1409.                          WHERE (sjsch.job_id = sjv.job_id)),
  1410.          has_target = (SELECT COUNT(*)
  1411.                        FROM msdb.dbo.sysjobservers sjs
  1412.                        WHERE (sjs.job_id = sjv.job_id)),
  1413.          type = fj.type
  1414.   FROM #filtered_jobs                         fj
  1415.        LEFT OUTER JOIN msdb.dbo.sysjobs_view  sjv ON (fj.job_id = sjv.job_id)
  1416.        LEFT OUTER JOIN msdb.dbo.sysoperators  so1 ON (sjv.notify_email_operator_id = so1.id)
  1417.        LEFT OUTER JOIN msdb.dbo.sysoperators  so2 ON (sjv.notify_netsend_operator_id = so2.id)
  1418.        LEFT OUTER JOIN msdb.dbo.sysoperators  so3 ON (sjv.notify_page_operator_id = so3.id)
  1419.        LEFT OUTER JOIN msdb.dbo.syscategories sc  ON (sjv.category_id = sc.category_id)
  1420.   ORDER BY sjv.job_id
  1421.  
  1422.   -- Clean up
  1423.   DROP TABLE #job_execution_state
  1424.   DROP TABLE #filtered_jobs
  1425.   DROP TABLE #xp_results
  1426. END
  1427. go
  1428.  
  1429.  
  1430. use master
  1431. go
  1432.  
  1433. --------------------------------------------------------------------------------
  1434. -- SQLDMO stored procedures added after release into sqldmo.sql file
  1435.  
  1436.     -- sp_MSscriptdb_worker
  1437.     -- sp_MStablekeys
  1438.     -- sp_MSloginmappings
  1439.     -- sp_MSdbuseraccess
  1440.     -- sp_MSobjectprivs
  1441.     -- sp_MSforeachdb
  1442.     -- sp_MSforeachtable
  1443. --------------------------------------------------------------------------------
  1444.  
  1445. if exists (select * from master..sysobjects where (OBJECTPROPERTY(id, N'IsProcedure') = 1 or OBJECTPROPERTY(id, N'IsExtendedProc') = 1) and name = N'sp_MSscriptdb_worker')
  1446.     drop procedure sp_MSscriptdb_worker
  1447. go
  1448. if exists (select * from master..sysobjects where (OBJECTPROPERTY(id, N'IsProcedure') = 1 or OBJECTPROPERTY(id, N'IsExtendedProc') = 1) and name = N'sp_MStablekeys')
  1449.     drop procedure sp_MStablekeys
  1450. go
  1451. if exists (select * from master..sysobjects where (OBJECTPROPERTY(id, N'IsProcedure') = 1 or OBJECTPROPERTY(id, N'IsExtendedProc') = 1) and name = N'sp_MSloginmappings')
  1452.     drop procedure sp_MSloginmappings
  1453. go
  1454. if exists (select * from master..sysobjects where (OBJECTPROPERTY(id, N'IsProcedure') = 1 or OBJECTPROPERTY(id, N'IsExtendedProc') = 1) and name = N'sp_MSdbuseraccess')
  1455.     drop procedure sp_MSdbuseraccess
  1456. go
  1457. if exists (select * from master..sysobjects where (OBJECTPROPERTY(id, N'IsProcedure') = 1 or OBJECTPROPERTY(id, N'IsExtendedProc') = 1) and name = N'sp_MSobjectprivs')
  1458.     drop procedure sp_MSobjectprivs
  1459. go
  1460. if exists (select * from master..sysobjects where (OBJECTPROPERTY(id, N'IsProcedure') = 1 or OBJECTPROPERTY(id, N'IsExtendedProc') = 1) and name = N'sp_MSforeachdb')
  1461.     drop procedure sp_MSforeachdb
  1462. go
  1463. if exists (select * from master..sysobjects where (OBJECTPROPERTY(id, N'IsProcedure') = 1 or OBJECTPROPERTY(id, N'IsExtendedProc') = 1) and name = N'sp_MSforeachtable')
  1464.     drop procedure sp_MSforeachtable
  1465. go
  1466.  
  1467.  
  1468. /*-----------------------------------------------------*/
  1469. /*-----------------------------------------------------*/
  1470. print N''
  1471. print N'Creating sp_MSforeachdb'
  1472. print N''
  1473. go
  1474.  
  1475. /*
  1476.  * The following table definition will be created by SQLDMO at start of each connection.
  1477.  * We don't create it here temporarily because we need it in Exec() or upgrade won't work.
  1478.  */
  1479.  
  1480. create proc sp_MSforeachdb
  1481.     @command1 nvarchar(2000), @replacechar nchar(1) = N'?', @command2 nvarchar(2000) = null, @command3 nvarchar(2000) = null,
  1482.     @precommand nvarchar(2000) = null, @postcommand nvarchar(2000) = null
  1483. as
  1484.     /* This proc returns one or more rows for each accessible db, with each db defaulting to its own result set */
  1485.     /* @precommand and @postcommand may be used to force a single result set via a temp table. */
  1486.  
  1487.     /* Preprocessor won't replace within quotes so have to use str(). */
  1488.     declare @inaccessible nvarchar(12), @invalidlogin nvarchar(12), @dbinaccessible nvarchar(12)
  1489.     select @inaccessible = ltrim(str(convert(int, 0x03e0), 11))
  1490.     select @invalidlogin = ltrim(str(convert(int, 0x40000000), 11))
  1491.     select @dbinaccessible = N'0x80000000'        /* SQLDMODbUserProf_InaccessibleDb; the negative number doesn't work in convert() */
  1492.  
  1493.     if (@precommand is not null)
  1494.         exec(@precommand)
  1495.  
  1496.     declare @origdb nvarchar(128)
  1497.     select @origdb = db_name()
  1498.  
  1499.     /* If it's a single user db and there's an entry for it in sysprocesses who isn't us, we can't use it. */
  1500.    /* Create the select */
  1501.     exec(N'declare hCForEach cursor global for select name from master..sysdatabases d ' +
  1502.             N' where (d.status & ' + @inaccessible + N' = 0)' +
  1503.             N' and ((DATABASEPROPERTY(d.name, ''issingleuser'') = 0 and (has_dbaccess(d.name) = 1)) or ' +
  1504.             N' ( DATABASEPROPERTY(d.name, ''issingleuser'') = 1 and not exists ' +
  1505.             N' (select * from master..sysprocesses p where dbid = d.dbid and p.spid <> @@spid)))' )
  1506.  
  1507.     declare @retval int
  1508.     select @retval = @@error
  1509.     if (@retval = 0)
  1510.         exec @retval = sp_MSforeach_worker @command1, @replacechar, @command2, @command3
  1511.  
  1512.     if (@retval = 0 and @postcommand is not null)
  1513.         exec(@postcommand)
  1514.  
  1515.    declare @tempdb nvarchar(258)
  1516.    SELECT @tempdb = REPLACE(@origdb, N']', N']]')
  1517.    exec (N'use ' + N'[' + @tempdb + N']')
  1518.  
  1519.     return @retval
  1520. go
  1521. /* End sp_MSforeachdb */
  1522.  
  1523. /*-----------------------------------------------------*/
  1524. /*-----------------------------------------------------*/
  1525. print N''
  1526. print N'Creating sp_MSforeachtable'
  1527. print N''
  1528. go
  1529.  
  1530. create proc sp_MSforeachtable
  1531.     @command1 nvarchar(2000), @replacechar nchar(1) = N'?', @command2 nvarchar(2000) = null,
  1532.    @command3 nvarchar(2000) = null, @whereand nvarchar(2000) = null,
  1533.     @precommand nvarchar(2000) = null, @postcommand nvarchar(2000) = null
  1534. as
  1535.     /* This proc returns one or more rows for each table (optionally, matching @where), with each table defaulting to its own result set */
  1536.     /* @precommand and @postcommand may be used to force a single result set via a temp table. */
  1537.  
  1538.     /* Preprocessor won't replace within quotes so have to use str(). */
  1539.     declare @mscat nvarchar(12)
  1540.     select @mscat = ltrim(str(convert(int, 0x0002)))
  1541.  
  1542.     if (@precommand is not null)
  1543.         exec(@precommand)
  1544.  
  1545.     /* Create the select */
  1546.    exec(N'declare hCForEach cursor global for select ''['' + REPLACE(user_name(uid), N'']'', N'']]'') + '']'' + ''.'' + ''['' + REPLACE(object_name(id), N'']'', N'']]'') + '']'' from sysobjects o '
  1547.          + N' where OBJECTPROPERTY(o.id, N''IsUserTable'') = 1 ' + N' and o.category & ' + @mscat + N' = 0 '
  1548.          + @whereand)
  1549.     declare @retval int
  1550.     select @retval = @@error
  1551.     if (@retval = 0)
  1552.         exec @retval = sp_MSforeach_worker @command1, @replacechar, @command2, @command3
  1553.  
  1554.     if (@retval = 0 and @postcommand is not null)
  1555.         exec(@postcommand)
  1556.  
  1557.     return @retval
  1558. go
  1559. /* End sp_MSforeachtable */
  1560.  
  1561.  
  1562.  
  1563. /*******************************************************************************/
  1564. print N''
  1565. print N'Creating sp_MSscriptdb_worker'
  1566. print N''
  1567. go
  1568. create procedure sp_MSscriptdb_worker
  1569. as
  1570.     set nocount on
  1571.  
  1572.    declare @PageSize int;
  1573.    select @PageSize = (low/1024) from master..spt_values where number = 1 and type = N'E'
  1574.  
  1575.     create table #tempFG
  1576.     (
  1577.      cDefault     int,                                  /* 1 for default FG, 0 for user defined */
  1578.      cDBFile      int,                                  /* 1 for DB file, 0 for Log file */
  1579.       cSize        int,                                  /* in 8K page */
  1580.       cMaxSize     int,
  1581.       cGrowth      int,
  1582.      cGrowthType  int,                                  /* 1 for GrowthInMB, 0 for GrowthInPercent */
  1583.      cFGName      nvarchar(132) NOT NULL,      /* FG name */
  1584.       cName        nchar(132) NOT NULL,         /* Logical */
  1585.       cFileName    nchar(264) NOT NULL,        /* Physical */
  1586.     )
  1587.  
  1588.    /* Default FileGroup first, which should cover all the log files */
  1589.    /* This one to pick up all the db files in Primary file group, while group id = 1 */
  1590.    insert #tempFG select 1, 1, (o.size * @PageSize)/1024, (case when (o.maxsize < 1) then o.maxsize else (o.maxsize * @PageSize)/1024 end), o.growth, (case when (o.status & 0x100000 = 0) then 1 else 0 end), g.groupname, o.name, o.filename from sysfiles o, sysfilegroups g where g.groupid = 1 and g.groupid = o.groupid and (o.status & 0x40) = 0
  1591.    /* This one to pick up all the log files in Primary file group, while group id = 0, note that group id 0 does not exist in sysfilegroups */
  1592.    insert #tempFG select 1, 0, (o.size * @PageSize)/1024, (case when (o.maxsize < 1) then o.maxsize else (o.maxsize * @PageSize)/1024 end), o.growth, (case when (o.status & 0x100000 = 0) then 1 else 0 end), N'PRIMARY', o.name, o.filename from sysfiles o where o.groupid = 0 and (o.status & 0x40) <> 0
  1593.    /* Other FileGroups, we should have DBFiles, no log files */
  1594.  
  1595.     create table #tempID
  1596.    (
  1597.         cGroupID int
  1598.     )
  1599.    insert #tempID select groupid from sysfilegroups where groupid <> 1
  1600.  
  1601.    declare @FGid int
  1602.     exec(N'declare hC cursor global for select cGroupID from #tempID')
  1603.     open hC
  1604.     fetch hC into @FGid
  1605.     while (@@fetch_status >= 0) begin
  1606.       insert #tempFG select 0, 1, (o.size * @PageSize)/1024, (case when (o.maxsize < 1) then o.maxsize else (o.maxsize * @PageSize)/1024 end), o.growth, (case when (o.status & 0x100000 = 0) then 1 else 0 end), g.groupname, o.name, o.filename from sysfiles o, sysfilegroups g where g.groupid = @FGid and g.groupid = o.groupid and (o.status & 0x40) = 0
  1607.       fetch hC into @FGid
  1608.    end
  1609.     deallocate hC
  1610.  
  1611.    select * from #tempFG
  1612.    DROP TABLE #tempFG
  1613.  
  1614. go
  1615. /* End sp_MSscriptdb_worker */
  1616.  
  1617.  
  1618. /*******************************************************************************/
  1619. print N''
  1620. print N'Creating sp_MStablekeys'
  1621. print N''
  1622. go
  1623.  
  1624. create procedure sp_MStablekeys
  1625. @tablename nvarchar(776) = null, @colname nvarchar(258) = null, @type int = null, @keyname nvarchar(517) = null, @flags int = null
  1626. as
  1627.     /* This proc returns the table's DRI keys.  @type is the type(s) of key(s) to return. */
  1628.     /* Make sure @type is only the key types (DRI_PRIMARYKEY, DRI_UNIQUE, DRI_REFERENCE). */
  1629.     if (@type is null)
  1630.         select @type = 0x000e
  1631.     else
  1632.         select @type = @type & 0x000e
  1633.  
  1634.     /* Flags usage:  For daVinci, to pass call thru to sp_MStablerefs. */
  1635.     if (@flags is null)
  1636.         select @flags = 0
  1637.  
  1638.     set nocount on
  1639.     create table #spkeys
  1640.     (
  1641.         cType                tinyint            NOT NULL,    /* key Type */
  1642.         cName                nvarchar(258)        NOT NULL,    /* key Name */
  1643.         cFlags                int                NULL,        /* e.g., 1 = clustered for PK/Unique */
  1644.         cColCount            int                NULL,        /* number of columns (or column pairs) in the key */
  1645.         cFillFactor            tinyint            NULL,        /* Fill factor of index creation */
  1646.         cRefTable            nvarchar(520)        NULL,        /* owner-qual Referenced table name for FKs */
  1647.         cRefKey                nvarchar(260)        NULL,        /* name of referenced key in referenced table */
  1648.             -- Note:  cConstID replaces the column list used in 6.0, for speed.
  1649.             -- The output set MUST replace this with either index_col(@tablename, cIndexID, 1-16) and NULL * 16
  1650.             -- (for PK/UQ) UNION col_name(r.fkeyid, r.fkey1-16) and col_name(r.rkeyid, r.rkey1-16), for SQLDMO,
  1651.             -- and these MUST BE nvarchar(132) for alignment in the SQLDMO cache structure!
  1652.         cConstID            int                NULL,        /* Reference constraint ID, if Foreign Key  */
  1653.         cIndexID            int                NULL,        /* ID of this key's index, if PK/UQ */
  1654.         cGroupName        sysname        NULL,        /* FileGroup name of this key, if PK/UQ */
  1655.         cDisabled        int                NULL,        /* 0 if enabled, 1 if disabled */
  1656.         cPrimaryFG        int                NULL,        /* 1 if primary FG, 0 otherwise */
  1657.     )
  1658.  
  1659.     declare @cType int, @cName nvarchar(258), @cFlags int, @cRefTable nvarchar(520), @fillfactor tinyint
  1660.     declare @objid int, @constid int, @indid int, @keycnt int, @q1 nvarchar(2000), @q2 nvarchar(2000), @objtype int, @groupname sysname
  1661.     declare @haskeytypes int, @wantkeytypes int
  1662.    declare @cDisabled int, @PrimaryFG int
  1663.  
  1664.     /* First see if @keyname was defined, and override @tablename and @type if so. */
  1665.     if (@keyname is not null)
  1666.     begin
  1667.          select @objid = id, @type = power(2, status & 0x0f) from sysconstraints where constid = object_id(@keyname)
  1668.          if (@objid is null)    begin
  1669.             RAISERROR (15001, -1, -1, @keyname)
  1670.             return 1
  1671.          end
  1672.          /* Now get the tablename for the index_col below */
  1673.          select @tablename = N'[' + REPLACE(user_name(uid), N']', N']]') + N']' + N'.' + N'[' + REPLACE(name, N']', N']]') + N']' from sysobjects where id = @objid
  1674.     end else begin
  1675.         /* Want all keys for this table (of @type type). */
  1676.         select @objid = id, @objtype = (case when OBJECTPROPERTY(id, N'IsTable') = 1 then 1 else 0 end), @haskeytypes = category & 0x0604
  1677.             from sysobjects where id = object_id(@tablename)
  1678.         if (@objid is null)    begin
  1679.             RAISERROR (15001, -1, -1, @tablename)
  1680.             return 1
  1681.         end
  1682.         if (@objtype <> 1)    begin
  1683.             RAISERROR (15218, -1, -1, @tablename)
  1684.             return 1
  1685.         end
  1686.         if @colname is not null and not exists (select * from syscolumns where id = @objid and name = @colname) begin
  1687.             RAISERROR (15253, -1, -1, @colname, @tablename)
  1688.             return 1
  1689.         end
  1690.  
  1691.         /* Skip cursor opening if we don't have any keys (of the type wanted); return a set anyway, for the cache. */
  1692.         if (@haskeytypes = 0)
  1693.             goto ReturnSet
  1694.  
  1695.         /* Map from the input bitmask to the category bitmask */
  1696.         select @wantkeytypes = 0
  1697.         if ((@type & power(2, 1)) <> 0)
  1698.             select @wantkeytypes = @wantkeytypes | 0x200
  1699.         if ((@type & power(2, 2)) <> 0)
  1700.             select @wantkeytypes = @wantkeytypes | 0x400
  1701.         if ((@type & power(2, 3)) <> 0)
  1702.             select @wantkeytypes = @wantkeytypes | 0x4
  1703.         if ((@haskeytypes & @wantkeytypes) = 0)
  1704.             goto ReturnSet
  1705.     end
  1706.  
  1707.     /* Preprocessor won't replace within quotes so have to use str(). */
  1708.     declare @sysgenname nvarchar(12), @pkstr nvarchar(12), @uqstr nvarchar(12), @fkstr nvarchar(12), @objtypebits nvarchar(12)
  1709.     select @sysgenname = ltrim(str(convert(int, 0x00020000)))
  1710.     select @pkstr = ltrim(str(convert(int, 1)))
  1711.     select @uqstr = ltrim(str(convert(int, 2)))
  1712.     select @fkstr = ltrim(str(convert(int, 3)))
  1713.     select @objtypebits = ltrim(str(convert(int, 0x0f)))
  1714.  
  1715.     /* Other ints we need strings for */
  1716.     declare @objidstr nvarchar(12), @typestr nvarchar(12)
  1717.     select @objidstr = ltrim(str(@objid))
  1718.     select @typestr = ltrim(str(@type))
  1719.  
  1720.     /* Qualifying key name. */
  1721.     declare @qualkeyname nvarchar(100)
  1722.     select @qualkeyname = null
  1723.     if (@keyname is not null) begin
  1724.       select @qualkeyname = N' and constid = object_id(''' + @keyname + N''')'
  1725.    end
  1726.  
  1727.     /*********************/
  1728.     /* Main cursor loop. */
  1729.     /*********************/
  1730. /*      exec(N'declare hC insensitive cursor for select constid, status & ' + @objtypebits + N', status & ' + @sysgenname +  */
  1731.     exec(N'declare hC cursor global for select constid, status & ' + @objtypebits + N', status & ' + @sysgenname +
  1732.             N' from sysconstraints where id = ' + @objidstr + N' and (' + @typestr + N' & power(2, status & 0x0f) != 0) ' + @qualkeyname)
  1733.     open hC
  1734.     fetch hC into @constid, @cType, @cFlags
  1735.     while (@@fetch_status >= 0) begin
  1736.         if (object_name(@constid) is null) begin
  1737.             raiserror 55555 N'Assert failed:  object_name(@constid) is null in sp_MStablekeys (pk/uq)'
  1738.             return 1
  1739.         end
  1740.  
  1741.         /* DRI_PRIMARYKEY, DRI_UNIQUE */
  1742.         if (@cType in (1, 2)) begin
  1743.             /* Get the index id enforcing this constraint. */
  1744.             select @indid = i.indid, @cName = o.name, @fillfactor = i.OrigFillFactor,
  1745.                     @cFlags = @cFlags | (case indid when 1 then 0x00000001 else 0 end),        /* test for clustered index */
  1746.                /* clustered index keys are part of non-clustered index key list, which cause incorrect sysindexes.keycnt */
  1747.                     @keycnt = case indid when 1 then keycnt else (select count(x.id) from sysindexkeys x where i.indid = x.indid and x.id = @objid) end,
  1748.                @groupname = f.groupname,
  1749.                @PrimaryFG = FILEGROUPPROPERTY( f.groupname, N'IsPrimaryFG' )
  1750.                 from sysindexes i, sysobjects o, sysfilegroups f
  1751.             /* Use '=' instead of 'LIKE' in comparision, so we can handle wide card character correctly */
  1752.                 where o.id = @constid and i.name = o.name and i.status & 0x1800 <> 0 and i.groupid = f.groupid
  1753.             if (@indid is null) begin
  1754.                 raiserror 77777 N'Assert failed:  @indid is null in sp_MStablekeys (pk/uq)'
  1755.                 return 1
  1756.             end
  1757.  
  1758.             /* Load our temp table. */
  1759.             insert #spkeys values (@cType, @cName, @cFlags, @keycnt, @fillfactor, null, null, null, @indid, @groupname, 0, @PrimaryFG)
  1760.         end
  1761.  
  1762.         /* DRI_REFERENCE */
  1763.         else if (@cType in (3)) begin
  1764.             /* Get the key column information from sysreferences. */
  1765.          select @keycnt = r.keycnt, @cName = object_name(r.constid), @cRefTable = N'[' + user_name(o.uid) + N']' + N'.' + N'[' + o.name + N']',
  1766.                @cDisabled = OBJECTPROPERTY( r.constid, N'CnstIsDisabled' )
  1767.             from sysreferences r, sysobjects o where r.constid = @constid and o.id = r.rkeyid
  1768.  
  1769.             /* Follow r.rkeyindid back to sysindexes to get the ref key name. */
  1770.             declare @cRefKey nvarchar(132)
  1771.             select @cRefKey = i.name, @cFlags = c.status from sysreferences r, sysindexes i, sysconstraints c
  1772.                 where c.constid = r.constid and r.constid = @constid
  1773.                 and i.id = r.rkeyid and i.indid = r.rkeyindid and i.status & 0x1800 <> 0
  1774.  
  1775.             /* Load our temp table. */
  1776.             insert #spkeys values (@cType, @cName, @cFlags, @keycnt, null, @cRefTable, @cRefKey, @constid, null, null, @cDisabled, 0)
  1777.         end        /* Key type */
  1778.  
  1779.         /* Get the next row. */
  1780.         fetch hC into @constid, @cType, @cFlags
  1781.     end            /* PRIMARY/UNIQUE */
  1782.     deallocate hC
  1783.  
  1784.     /* Now output the data */
  1785. ReturnSet:
  1786.     set nocount off
  1787.     select cType, cName, cFlags, cColCount, cFillFactor, cRefTable, cRefKey,
  1788.             cKeyCol1 = convert(nvarchar(132), index_col(@tablename, cIndexID, 1)),
  1789.             cKeyCol2 = convert(nvarchar(132), index_col(@tablename, cIndexID, 2)),    
  1790.             cKeyCol3 = convert(nvarchar(132), index_col(@tablename, cIndexID, 3)),
  1791.             cKeyCol4 = convert(nvarchar(132), index_col(@tablename, cIndexID, 4)),
  1792.             cKeyCol5 = convert(nvarchar(132), index_col(@tablename, cIndexID, 5)),
  1793.             cKeyCol6 = convert(nvarchar(132), index_col(@tablename, cIndexID, 6)),    
  1794.             cKeyCol7 = convert(nvarchar(132), index_col(@tablename, cIndexID, 7)),
  1795.             cKeyCol8 = convert(nvarchar(132), index_col(@tablename, cIndexID, 8)),
  1796.             cKeyCol9 = convert(nvarchar(132), index_col(@tablename, cIndexID, 9)),
  1797.             cKeyCol10 = convert(nvarchar(132), index_col(@tablename, cIndexID, 10)),
  1798.             cKeyCol11 = convert(nvarchar(132), index_col(@tablename, cIndexID, 11)),
  1799.             cKeyCol12 = convert(nvarchar(132), index_col(@tablename, cIndexID, 12)),
  1800.             cKeyCol13 = convert(nvarchar(132), index_col(@tablename, cIndexID, 13)),
  1801.             cKeyCol14 = convert(nvarchar(132), index_col(@tablename, cIndexID, 14)),    
  1802.             cKeyCol15 = convert(nvarchar(132), index_col(@tablename, cIndexID, 15)),
  1803.             cKeyCol16 = convert(nvarchar(132), index_col(@tablename, cIndexID, 16)),
  1804.             cRefCol1 = convert(nvarchar(132), null),
  1805.             cRefCol2 = convert(nvarchar(132), null),
  1806.             cRefCol3 = convert(nvarchar(132), null),
  1807.             cRefCol4 = convert(nvarchar(132), null),
  1808.             cRefCol5 = convert(nvarchar(132), null),
  1809.             cRefCol6 = convert(nvarchar(132), null),
  1810.             cRefCol7 = convert(nvarchar(132), null),
  1811.             cRefCol8 = convert(nvarchar(132), null),
  1812.             cRefCol9 = convert(nvarchar(132), null),
  1813.             cRefCol10 = convert(nvarchar(132), null),
  1814.             cRefCol11 = convert(nvarchar(132), null),
  1815.             cRefCol12 = convert(nvarchar(132), null),
  1816.             cRefCol13 = convert(nvarchar(132), null),
  1817.             cRefCol14 = convert(nvarchar(132), null),
  1818.             cRefCol15 = convert(nvarchar(132), null),
  1819.             cRefCol16 = convert(nvarchar(132), null),
  1820.             cIndexID,
  1821.             cGroupName,
  1822.          cDisabled,
  1823.           cPrimaryFG
  1824.         from #spkeys where cType in (1, 2)
  1825.             and (@colname is null or
  1826.                 index_col(@tablename, cIndexID, 1) = @colname or
  1827.                 index_col(@tablename, cIndexID, 2) = @colname or
  1828.                 index_col(@tablename, cIndexID, 3) = @colname or
  1829.                 index_col(@tablename, cIndexID, 4) = @colname or
  1830.                 index_col(@tablename, cIndexID, 5) = @colname or
  1831.                 index_col(@tablename, cIndexID, 6) = @colname or
  1832.                 index_col(@tablename, cIndexID, 7) = @colname or
  1833.                 index_col(@tablename, cIndexID, 8) = @colname or
  1834.                 index_col(@tablename, cIndexID, 9) = @colname or
  1835.                 index_col(@tablename, cIndexID, 10) = @colname or
  1836.                 index_col(@tablename, cIndexID, 11) = @colname or
  1837.                 index_col(@tablename, cIndexID, 12) = @colname or
  1838.                 index_col(@tablename, cIndexID, 13) = @colname or
  1839.                 index_col(@tablename, cIndexID, 14) = @colname or
  1840.                 index_col(@tablename, cIndexID, 15) = @colname or
  1841.                 index_col(@tablename, cIndexID, 16) = @colname
  1842.             )
  1843.         UNION
  1844.         select c.cType, c.cName, c.cFlags, c.cColCount, c.cFillFactor, c.cRefTable, c.cRefKey,
  1845.             cKeyCol1 = convert(nvarchar(132), col_name(r.fkeyid, r.fkey1)),
  1846.             cKeyCol2 = convert(nvarchar(132), col_name(r.fkeyid, r.fkey2)),
  1847.             cKeyCol3 = convert(nvarchar(132), col_name(r.fkeyid, r.fkey3)),
  1848.             cKeyCol4 = convert(nvarchar(132), col_name(r.fkeyid, r.fkey4)),
  1849.             cKeyCol5 = convert(nvarchar(132), col_name(r.fkeyid, r.fkey5)),
  1850.             cKeyCol6 = convert(nvarchar(132), col_name(r.fkeyid, r.fkey6)),
  1851.             cKeyCol7 = convert(nvarchar(132), col_name(r.fkeyid, r.fkey7)),
  1852.             cKeyCol8 = convert(nvarchar(132), col_name(r.fkeyid, r.fkey8)),
  1853.             cKeyCol9 = convert(nvarchar(132), col_name(r.fkeyid, r.fkey9)),
  1854.             cKeyCol10 = convert(nvarchar(132), col_name(r.fkeyid, r.fkey10)),
  1855.             cKeyCol11 = convert(nvarchar(132), col_name(r.fkeyid, r.fkey11)),
  1856.             cKeyCol12 = convert(nvarchar(132), col_name(r.fkeyid, r.fkey12)),
  1857.             cKeyCol13 = convert(nvarchar(132), col_name(r.fkeyid, r.fkey13)),
  1858.             cKeyCol14 = convert(nvarchar(132), col_name(r.fkeyid, r.fkey14)),
  1859.             cKeyCol15 = convert(nvarchar(132), col_name(r.fkeyid, r.fkey15)),
  1860.             cKeyCol16 = convert(nvarchar(132), col_name(r.fkeyid, r.fkey16)),
  1861.             cRefCol1 = convert(nvarchar(132), col_name(r.rkeyid, r.rkey1)),
  1862.             cRefCol2 = convert(nvarchar(132), col_name(r.rkeyid, r.rkey2)),    
  1863.             cRefCol3 = convert(nvarchar(132), col_name(r.rkeyid, r.rkey3)),
  1864.             cRefCol4 = convert(nvarchar(132), col_name(r.rkeyid, r.rkey4)),
  1865.             cRefCol5 = convert(nvarchar(132), col_name(r.rkeyid, r.rkey5)),
  1866.             cRefCol6 = convert(nvarchar(132), col_name(r.rkeyid, r.rkey6)),
  1867.             cRefCol7 = convert(nvarchar(132), col_name(r.rkeyid, r.rkey7)),
  1868.             cRefCol8 = convert(nvarchar(132), col_name(r.rkeyid, r.rkey8)),
  1869.             cRefCol9 = convert(nvarchar(132), col_name(r.rkeyid, r.rkey9)),
  1870.             cRefCol10 = convert(nvarchar(132), col_name(r.rkeyid, r.rkey10)),
  1871.             cRefCol11 = convert(nvarchar(132), col_name(r.rkeyid, r.rkey11)),
  1872.             cRefCol12 = convert(nvarchar(132), col_name(r.rkeyid, r.rkey12)),
  1873.             cRefCol13 = convert(nvarchar(132), col_name(r.rkeyid, r.rkey13)),
  1874.             cRefCol14 = convert(nvarchar(132), col_name(r.rkeyid, r.rkey14)),
  1875.             cRefCol15 = convert(nvarchar(132), col_name(r.rkeyid, r.rkey15)),
  1876.             cRefCol16 = convert(nvarchar(132), col_name(r.rkeyid, r.rkey16)),
  1877.             cIndexID,
  1878.             cGroupName,
  1879.          cDisabled,
  1880.           cPrimaryFG
  1881.         from #spkeys c, sysreferences r where c.cType = 3 and r.constid = c.cConstID
  1882.             and (@colname is null or
  1883.                 col_name(r.fkeyid, r.fkey1) = @colname or
  1884.                 col_name(r.fkeyid, r.fkey2) = @colname or
  1885.                 col_name(r.fkeyid, r.fkey3) = @colname or
  1886.                 col_name(r.fkeyid, r.fkey4) = @colname or
  1887.                 col_name(r.fkeyid, r.fkey5) = @colname or
  1888.                 col_name(r.fkeyid, r.fkey6) = @colname or
  1889.                 col_name(r.fkeyid, r.fkey7) = @colname or
  1890.                 col_name(r.fkeyid, r.fkey8) = @colname or
  1891.                 col_name(r.fkeyid, r.fkey9) = @colname or
  1892.                 col_name(r.fkeyid, r.fkey10) = @colname or
  1893.                 col_name(r.fkeyid, r.fkey11) = @colname or
  1894.                 col_name(r.fkeyid, r.fkey12) = @colname or
  1895.                 col_name(r.fkeyid, r.fkey13) = @colname or
  1896.                 col_name(r.fkeyid, r.fkey14) = @colname or
  1897.                 col_name(r.fkeyid, r.fkey15) = @colname or
  1898.                 col_name(r.fkeyid, r.fkey16) = @colname
  1899.             )
  1900.         order by cType, cName
  1901.  
  1902.     if (@flags & 1 <> 0)
  1903.         exec sp_MStablerefs @tablename, N'actualkeycols', N'foreign'
  1904.  
  1905. go
  1906. /* End sp_MStablekeys */
  1907.  
  1908.  
  1909. /*******************************************************************************/
  1910.  
  1911. print N''
  1912. print N'Creating sp_MSloginmappings'
  1913. print N''
  1914. go
  1915.  
  1916.  
  1917.  
  1918. create proc sp_MSloginmappings
  1919.     @loginname nvarchar(258) = null, @flags int = 0
  1920. as
  1921.     /*
  1922.      * @flags bits:
  1923.      *        0x01    - current db only
  1924.      */
  1925.     /*
  1926.      * Added @dbname so dbo can see everyone in current database.
  1927.      * Use hacky 4.21 syntax so it will run there, instead of a case..when.
  1928.      */
  1929.     declare @checkmultilogin int
  1930.     select @checkmultilogin = 1
  1931.     if ((@flags & 0x01 <> 0) and user_id() = 1)
  1932.         select @checkmultilogin = 0
  1933.  
  1934.     declare @logincount int
  1935.     select @logincount = 0
  1936.     if (@loginname is not null)
  1937.         select @logincount = count(*) from syslogins where loginname = @loginname
  1938.  
  1939.     /* Gotta be sa or dbo to see other than just current login. */
  1940.     declare @numlogins int, @whereloginname nvarchar(258), @name nvarchar(258), @retval int
  1941.     if (@loginname is null)
  1942.         select @numlogins = 2
  1943.     else
  1944.         select @numlogins = count(*) from syslogins where loginname = @loginname
  1945.  
  1946.     if (@numlogins = 0) begin
  1947.         RAISERROR (15007, -1, -1, @loginname)        /* Login not found */
  1948.         return 1
  1949.     end
  1950.     if (@checkmultilogin <> 0) begin
  1951.       /* We do not want to allow everybody to execute this SP */
  1952.         if (is_member(N'db_ddladmin') <> 1 and is_member(N'db_owner') <> 1 and is_member(N'db_accessadmin') <> 1 and is_member(N'db_securityadmin') <> 1 and (@numlogins > 1 or suser_sid() <> suser_sid(@loginname))) begin
  1953.             RAISERROR (14301, -1, -1, N'')                /* Only sa can see other than the current login */
  1954.             return 1
  1955.         end
  1956.     end
  1957.     if (@loginname is not null)
  1958.         select @whereloginname = N' and loginname = ''' + @loginname + N''''
  1959.    else
  1960.       select @whereloginname = N' '
  1961.  
  1962.     /*
  1963.      * This proc returns a result set with one or more rows for each database for which a login is a user or aliased to one.
  1964.      * If loginname is specified, the results are limited to that login.  First load a temp table with all logins that are
  1965.      * in a db, then add those which aren't mapped to any db.
  1966.      */
  1967.     create table #loginmappings(
  1968.         LoginName            nvarchar(128)        NULL,
  1969.         DBName                nvarchar(128)        NULL,
  1970.         UserName            nvarchar(128)        NULL,
  1971.         AliasName            nvarchar(128)        NULL
  1972.     )
  1973.     if (@flags & 0x01 <> 0) begin
  1974.         INSERT #loginmappings select l.loginname, db_name(), u.name, null from master..syslogins l, sysusers u where l.sid = u.sid and l.loginname is not NULL
  1975.         /*
  1976.          * We only allow multi-db on a 6.x server because dynamic exec() didn't exist before then,
  1977.          * hence there is no way to loop thru every database.  This is caught in SQLDMO so no
  1978.          * need for error message here; we'll just return no result sets.
  1979.          */
  1980.     end else begin
  1981.         exec @retval = sp_MSforeachdb
  1982.             N'use [?] INSERT #loginmappings select l.loginname, db_name(), u.name, null from master..syslogins l, sysusers u where l.sid = u.sid and l.loginname is not NULL'
  1983.         if (@retval <> 0)
  1984.             return 1
  1985.         insert #loginmappings select l.loginname, null, null, null from master..syslogins l where l.loginname not in (select LoginName from #loginmappings) and l.loginname is not NULL
  1986.     end
  1987.  
  1988.     /*
  1989.      * Now bring them out by loginname, each in its own result set.
  1990.      * If this is for all logins, we'll return all logins; if for curdb,
  1991.      * only those in #loginmappings (i.e. only those mapped in curdb).
  1992.      */
  1993.     exec(N'declare hCForEachLogin cursor global for select loginname from master..syslogins where loginname is not NULL ' + @whereloginname + N' order by loginname')
  1994.     if (@@error = 0)
  1995.         open hCForEachLogin
  1996.     if (@@error <> 0)
  1997.         return @@error
  1998.     fetch hCForEachLogin into @name
  1999.     while (@@fetch_status >= 0) begin
  2000.       /* Use '=' instead of 'LIKE' in comparision, so we can handle wide card character correctly */
  2001.         if ((@flags & 0x01 = 0) or exists (select * from #loginmappings where LoginName = @name))
  2002.             select * from #loginmappings where LoginName = @name
  2003.         fetch hCForEachLogin into @name
  2004.     end /* FETCH_SUCCESS */
  2005.     close hCForEachLogin
  2006.     deallocate hCForEachLogin
  2007.     return @@error
  2008. go
  2009. /* End sp_MSloginmappings */
  2010.  
  2011.  
  2012. /*******************************************************************************/
  2013. /*******************************************************************************/
  2014. /* exec sp_MSdbuseraccess 'perm', 'dbname' -- selecting priv bit from specified db                       */
  2015. /* exec sp_MSdbuseraccess 'db', 'dbname'   -- select databases, need to change db if dbname is specified */
  2016. /* exec sp_MSdbuseraccess 'init', 'dbname' -- noop                                                       */
  2017. /*******************************************************************************/
  2018. print N''
  2019. print N'Creating sp_MSdbuseraccess'
  2020. print N''
  2021. go
  2022.  
  2023. create proc sp_MSdbuseraccess
  2024.     @mode nvarchar(10) = N'perm', @qual nvarchar(128) = N'%'
  2025. as
  2026.  
  2027.    set nocount on
  2028.  
  2029.    declare @accessbit int
  2030.     if (lower(@mode) like N'perm%') begin
  2031.       /* verify */
  2032.       declare @id int, @stat int, @inval int
  2033.       select @id = dbid, @stat = status from master..sysdatabases where name = @qual
  2034.       if (@id is null) begin
  2035.          RAISERROR (15001, -1, -1, @qual)
  2036.          return 1
  2037.       end
  2038.  
  2039.       /* Can we access this db? */
  2040.       declare @single int
  2041.       select @single = DATABASEPROPERTY( @qual, N'issingleuser' )
  2042. /*      if ((@single <> 0) or ((@stat & SQLDMODBStat_Inaccessible) <> 0)) begin  */
  2043.       if ((@single <> 0) or
  2044.          (DATABASEPROPERTY(@qual, N'isdetached') <> 0) or
  2045.          (DATABASEPROPERTY(@qual, N'isshutdown') <> 0) or
  2046.          (DATABASEPROPERTY(@qual, N'issuspect') <> 0) or
  2047.          (DATABASEPROPERTY(@qual, N'isoffline') <> 0) or
  2048.          (DATABASEPROPERTY(@qual, N'isinload') <> 0) or
  2049.          (DATABASEPROPERTY(@qual, N'isinrecovery') <> 0) or
  2050.          (DATABASEPROPERTY(@qual, N'isnotrecovered') <> 0)) begin
  2051.          select @inval = 0x80000000
  2052.          select @inval
  2053.          return 0
  2054.       end
  2055.       select @accessbit = has_dbaccess(@qual)
  2056.       if ( @accessbit <> 1) begin
  2057.          select @inval = 0x40000000
  2058.          select @inval
  2059.          return 0
  2060.       end
  2061.  
  2062.       /** OK, we can access this db, need to go to the specified database to get priv bit **/
  2063.       declare @dbTempname nvarchar(258)
  2064.       declare @tempindex int
  2065.       SELECT @dbTempname = REPLACE(@qual, N']', N']]')
  2066.       exec (N'[' + @dbTempname + N']' + N'..sp_MSdbuserpriv ')
  2067.       return 0
  2068.    end
  2069.  
  2070.    /* If 'db', we want to know if what kind of access we have to the specified databases */
  2071.    /* If we are not in master, then we are selecting single database, we want to correct role bit to save round trip */
  2072.    if (lower(@mode) like N'db%') begin
  2073.       /* Make sure we're either in master or only doing it to current db. */
  2074.       declare @dbrole int
  2075.       select @dbrole = 0x0000
  2076.  
  2077.       if (db_id() <> 1)
  2078.          select @qual = db_name()
  2079.  
  2080.       /* If dbname contains ', double it for the cursor, since cursor statement is inside of '' */
  2081.       declare @qual2 nvarchar(128)
  2082.       SELECT @qual2 = REPLACE(@qual, N'''', N'''''')
  2083.  
  2084.       /* Preprocessor won't replace within quotes so have to use str(). */
  2085.       declare @invalidlogin nvarchar(12)
  2086.       select @invalidlogin = ltrim(str(convert(int, 0x40000000), 11))
  2087.       declare @inaccessible nvarchar(12)
  2088.       select @inaccessible = ltrim(str(convert(int, 0x80000000), 11))
  2089.  
  2090.       /* We can't 'use' a database with a version below the minimum. */
  2091.       /* SQL6.0 minimum is 406; SQL65 requires 408.  SQL70 database version is 408 now, it might change later */
  2092.       declare @mindbver smallint
  2093.       if (@@microsoftversion >= 0x07000000)
  2094.          select @mindbver = 408
  2095.       else
  2096.          select @mindbver = 406
  2097.  
  2098.       create table #TmpDbUserProfile (
  2099.          dbid        int NOT NULL PRIMARY KEY,
  2100.          accessperms int NOT NULL
  2101.          )
  2102.  
  2103.       /* Select all matching databases -- we want an entry even for inaccessible ones. */
  2104.       declare @dbid smallint, @dbidstr nvarchar(12), @dbstat int, @dbname nvarchar(258), @dbver smallint
  2105.       declare @dbbits int, @dbbitstr nvarchar(12)
  2106.  
  2107.       /* !!! work around here, if name contains '[', LIKE operator can't find it, since LIKE operator it treating '[' as a wild char */
  2108.       /* !!! but @qual2 might be '%', then = operator does not work */
  2109.       declare @temp int
  2110.       select @tempindex = charindex(N'[', @qual2)
  2111.       if (@tempindex <> 0)
  2112.          exec(N'declare hCdbs cursor global for select name, dbid, status, version from master..sysdatabases where name = N''' + @qual2 + N'''')
  2113.       else
  2114.          exec(N'declare hCdbs cursor global for select name, dbid, status, version from master..sysdatabases where name like N''' + @qual2 + N'''')
  2115.  
  2116.       open hCdbs
  2117.  
  2118.       /* Loop for each database, and if it's accessible, recursively call ourselves to add it. */
  2119.       fetch hCdbs into @dbname, @dbid, @dbstat, @dbver
  2120.       while (@@fetch_status >= 0) begin
  2121.          /* Preprocessor won't replace within quotes so have to use str(). */
  2122.          select @dbidstr = ltrim(str(convert(int, @dbid)))
  2123.  
  2124.          /* If it's a single user db and there's an entry for it in sysprocesses who isn't us, we can't use it. */
  2125.          declare @single_lockedout int
  2126.          select @single_lockedout = DATABASEPROPERTY( @dbname, N'issingleuser' )
  2127.          if (@single_lockedout <> 0)
  2128.             select @single_lockedout = 0 where not exists
  2129.                (select * from master..sysprocesses p where dbid = @dbid and p.spid <> @@spid)
  2130.  
  2131.          /* First see if the db is accessible (not in load, recovery, offline, single-use with another user besides us, etc.) */
  2132. /*         if ((@single_lockedout <> 0) or ((@dbstat & SQLDMODBStat_Inaccessible) <> 0) or (@dbver < @mindbver)) begin   */
  2133.          if ((@single_lockedout <> 0) or
  2134.             (@dbver < @mindbver) or
  2135.             (DATABASEPROPERTY(@dbname, N'isdetached') <> 0) or
  2136.             (DATABASEPROPERTY(@dbname, N'isshutdown') <> 0) or
  2137.             (DATABASEPROPERTY(@dbname, N'issuspect') <> 0) or
  2138.             (DATABASEPROPERTY(@dbname, N'isoffline') <> 0) or
  2139.             (DATABASEPROPERTY(@dbname, N'isinload') <> 0) or
  2140.             (DATABASEPROPERTY(@dbname, N'isinrecovery') <> 0) or
  2141.             (DATABASEPROPERTY(@dbname, N'isnotrecovered') <> 0) ) begin
  2142.             /* Inaccessible, but we can set dbo if we're sa or suser_id() is db owner sid. */
  2143.             exec (N'insert #TmpDbUserProfile values (' + @dbidstr + N', ' + @inaccessible + N')')
  2144.             end
  2145.          else begin
  2146.             /* Find out whether the current user has access to the database */
  2147.             select @accessbit = has_dbaccess(@dbname)
  2148.             if ( @accessbit <> 1) begin
  2149.                exec (N'insert #TmpDbUserProfile values (' + @dbidstr + N', ' + @invalidlogin + N')')
  2150.                end
  2151.             else begin
  2152.                /* Yes, current user does have access to this database, we are not trying to get priv at this point */
  2153.                select @dbbits = 0x01ff
  2154.                select @dbbitstr = ltrim(convert(nvarchar(12), @dbbits))
  2155.                exec (N'insert #TmpDbUserProfile values (' + @dbidstr + N', ' + @dbbitstr + N')')
  2156.                end
  2157.             end
  2158.  
  2159.          fetch hCdbs into @dbname, @dbid, @dbstat, @dbver
  2160.       end /* while FETCH_SUCCESS */
  2161.       close hCdbs
  2162.       deallocate hCdbs
  2163.  
  2164.       /* 1. If on all databases, then dbrole is dummy, need to get it later */
  2165.       /* 2. Do not double the ' character(s) in database name */
  2166.       /* 3. To speed up connection, accessperms column only indicate whether the login user can access the db, it does not contain */
  2167.       /*    permission info, we will retrieve the permission info through sp_MSdbuserpriv when necessary */
  2168.       /* !!! work around here, if name contains '[', LIKE operator can't find it, since LIKE operator it treating '[' as a wild char */
  2169.       /* !!! but @qual2 might be '%', then = operator does not work */
  2170.       if (@tempindex <> 0)
  2171.          select o.name, o.version, o.crdate, suser_sname(o.sid), o.dbid, lSize = 0, NonDbo = 0, Status = o.status, spaceavail = 0,
  2172.             LogOnSepDev = 1, o.category, t.accessperms, @dbrole, DatabaseProperty(o.name, 'isfulltextenabled'), o.status2 from master..sysdatabases o left outer join #TmpDbUserProfile t on t.dbid = o.dbid where o.name = @qual order by o.name
  2173.       else
  2174.          select o.name, o.version, o.crdate, suser_sname(o.sid), o.dbid, lSize = 0, NonDbo = 0, Status = o.status, spaceavail = 0,
  2175.             LogOnSepDev = 1, o.category, t.accessperms, @dbrole, DatabaseProperty(o.name, 'isfulltextenabled'), o.status2 from master..sysdatabases o left outer join #TmpDbUserProfile t on t.dbid = o.dbid where o.name like @qual order by o.name
  2176.       DROP TABLE #TmpDbUserProfile
  2177.       return 0
  2178.    end
  2179. go
  2180. /* End sp_MSdbuseraccess */
  2181.  
  2182. /*******************************************************************************/
  2183. print N''
  2184. print N'Creating sp_MSobjectprivs'
  2185. print N''
  2186. go
  2187.  
  2188. create proc sp_MSobjectprivs
  2189.     @objname nvarchar(776) = null,
  2190.     @mode nvarchar(10) = N'object',    
  2191.     @objid int = null,                
  2192.     @srvpriv int = null,            
  2193.     @prottype int = null,            
  2194.     @grantee nvarchar(258) = null,        
  2195.    @flags int = 0,
  2196.    @rollup int = 0
  2197. as
  2198.  
  2199.     create table #objs(
  2200.         id  int NOT NULL
  2201.     )
  2202.  
  2203.     /* Temp table will hold output for final select */
  2204.     create table #output (
  2205.         action      int  NOT NULL,
  2206.         colid       int  NULL,
  2207.         uid         int  NOT NULL,
  2208.         protecttype int  NOT NULL,
  2209.         id          int  NOT NULL,
  2210.         grantor     int
  2211.     )
  2212.  
  2213.     create table #tmp(
  2214.         action   int   NOT NULL,
  2215.         uid      int   NOT NULL,
  2216.         protecttype int  NOT NULL,
  2217.     )
  2218.  
  2219.    /* mode    : 'object', 'user' or 'column'*/
  2220.    /*
  2221.     * Note:  This was expanded for 6.5 due to changes in sysprotects.columns usage, affecting
  2222.     * CPermission::ListPrivilegeColumns.  The following additional parameters are for this.
  2223.     */
  2224.    /* objid   : ID of the object we're querying */
  2225.    /* srvpriv : privilege that we're querying for (e.g. select) */
  2226.    /* prottype: Protect type, e.g. GRANT/REVOKE */
  2227.    /* grantee : Grantee name. */
  2228.  
  2229.    /*** @flags added for DaVinci uses.  If the bit isn't set, use 6.5 ***/
  2230.    /*** sp_MSobjectprivs '%s'                                         ***/
  2231.  
  2232.    /* 8.0: mode 'column', and grantee != null, we want user column level permissions for CTable/CView::ListUserColumnPermissions */
  2233.    /*      @rollup added to indicate special rollup result set for column level permission, set to 1 to roll up */
  2234.  
  2235.     /* @flags is for daVinci */
  2236.     if (@flags is null)
  2237.         select @flags = 0
  2238.  
  2239.     /* If @objid is not null, this is for the new query for perm cols. */
  2240.     if (@objid is not null) begin
  2241.         select u.name, o.name, a = col_name(p.id, a.number), a.low, a.high, a.number
  2242.             from master.dbo.spt_values a, dbo.sysprotects p, dbo.sysobjects o, dbo.sysusers u
  2243.             where p.id = @objid and p.action = @srvpriv and p.protecttype = @prottype
  2244.             and p.uid = user_id(@grantee)
  2245.             and p.columns != 0x01 and o.id = p.id and u.uid = o.uid
  2246.                 and convert(tinyint, substring(isnull(p.columns, 0x01), a.low, 1)) &
  2247.                     -- 6.5 changed so that the bit 0 position is an "invert the bits" indicator:
  2248.                     --        when 0, behaviour is the same as in prior versions, and other bits
  2249.                     --            indicate columns with the specified privilege
  2250.                     --        when 1, the other bits are indicate columns lacking the specified privilege
  2251.                     a.high <> (case when (substring(isnull(p.columns, 0x00), 1, 1) & 1 = 0) then 0 else a.high end)
  2252.                     and col_name(p.id, a.number) is not null
  2253.                     and a.type = N'P' and a.number <= (select count(*) from dbo.syscolumns where id = @objid) order by a
  2254.         return 0
  2255.     end
  2256.  
  2257.     set nocount on
  2258.  
  2259.     /*
  2260.      * To get around a 4.21 subquery bug where returning count(*) of 0 (for proc cols)
  2261.      * causes the result set to return no rows, we need two passes; one to get the
  2262.      * objects, and another to explicitly use a value (@cols) instead of a subquery.
  2263.      */
  2264.     declare @id int, @uid int, @cols int
  2265.     select @id = null, @uid = null
  2266.     if (@mode like N'us%') begin
  2267.        select @uid = user_id(@objname)
  2268.    end else if (@mode like N'col%') and (@objname is null) and (@grantee is not null) begin
  2269.       /* 8.0, special path to get column level permissions from all objects on the specified user */
  2270.       select @uid = user_id(@grantee)
  2271.     end else begin
  2272.       select @id = object_id(@objname)
  2273.    end
  2274.     if (@id is null and @uid is null) begin
  2275.         RAISERROR (15001, -1, -1, @objname)
  2276.         return 1
  2277.     end
  2278.  
  2279.     /* Get a temp list of objects we're interested in.  Do not include repl_* users. */
  2280.    /* This is the original code */
  2281.    insert #objs select distinct p.id from dbo.sysprotects p
  2282.        where (@id is null or p.id = @id)
  2283.           and (@uid is null or p.uid = @uid)
  2284.        and p.action in (193, 195, 196, 197, 224, 26) and p.uid not in (16382, 16383)
  2285.  
  2286.     /* Use a "fake cursor" by deleting successive id's from #objs, as this must run on 4.21 */
  2287.     select @id = min(id) from #objs
  2288.     while (@id is not null) begin
  2289.         select @cols = count(*) from dbo.syscolumns c where c.id = @id
  2290.       /* sysprotects.columns is for SELECT and UPDATE, NULL if it is INSERT or DELETE, since INSERT and DELETE can not be applied to column level */
  2291.       insert #output select p.action, (case when p.columns is null then -1 else a.number end), p.uid, p.protecttype, p.id, p.grantor
  2292.          from master.dbo.spt_values a, dbo.sysprotects p
  2293.          where convert(tinyint, substring( isnull(p.columns, 0x01), a.low, 1)) & a.high !=0
  2294.          and (p.id = @id)
  2295.          and (@uid is null or p.uid = @uid)
  2296.          and a.number <= @cols
  2297.          and a.type = N'P'
  2298.  
  2299.       declare @count int, @whataction int, @whatid int, @dup int, @whatprot int
  2300.  
  2301.       /* First pass to correct duplicates */
  2302.       select @count = count(*) from #output where id = @id and colid in (0, -1) and protecttype in (205, 204)
  2303.       if ( @count > 0 ) begin
  2304.          /* We might have duplicate rows for permission on single coulmn(s) at this point */
  2305.          /* Use a fake cursor to remove the duplicates first. */
  2306.          insert #tmp select action, uid, protecttype from #output where id = @id and colid in (0, -1) and protecttype in (205, 204)
  2307.          select @whataction = min(action) from #tmp
  2308.          select @whatid = uid from #tmp where action = @whataction
  2309.          while (@whataction is not null) begin
  2310.             if (@mode like N'col%') and (@objname is null) and (@grantee is not null) begin
  2311.                /* Special case for column level permissions on ALL objects for the specified user, we don't want the row(s) on the entire table */
  2312.                /* and we don't want the possible duplicate rows in single column(s) */
  2313.                delete #output where (@whatid = uid) and (colid not in (0, -1)) and (protecttype in (205, 204)) and action = @whataction
  2314.                       and (exists (select * from #output where (@whatid = uid) and (colid in (0, -1)) and action = @whataction) and (id = @id))
  2315.                delete #output where (@whatid = uid) and (colid in (0, -1)) and (action = @whataction) and (id = @id)
  2316.             end else if (@mode like N'use%') and (@objname is not null) begin
  2317.                /* Special case for the user mode, we do want to keep the entire table permissions */
  2318.                delete #output where (@whatid = uid) and (colid not in (0, -1)) and (protecttype in (205, 204)) and action = @whataction and (id = @id)
  2319.             end else begin
  2320.                /* Other cases */
  2321.                delete #output where (@whatid = uid) and (colid not in (0, -1)) and (protecttype in (205, 204)) and action = @whataction
  2322.             end
  2323.  
  2324.             delete #tmp where @whatid = uid
  2325.             select @whataction = min(action) from #tmp
  2326.             select @whatid = uid from #tmp where action = @whataction
  2327.          end
  2328.          delete #tmp
  2329.       end
  2330.  
  2331.       /* Second pass to correct protect type */
  2332.       select @count = count(*) from #output where id = @id and colid in (0, -1)
  2333.       if ( @count > 0 ) begin
  2334.          /* use another fake cursor to correct the protecttype */
  2335.          /* if there are multiple rows in #output for the same id and action, and if colid = 0 exist */
  2336.          /* then other rows should have different protecttype from the one in colid = 0 row */
  2337.          insert #tmp select action, uid, protecttype from #output where id = @id and colid in (0, -1)
  2338.          select @whataction = min(action) from #tmp
  2339.          select @whatid = uid from #tmp where action = @whataction
  2340.          select @whatprot = protecttype from #tmp where uid = @whatid and action = @whataction
  2341.          while (@whataction is not null) begin
  2342.                delete #output where id = @id and colid not in (0, -1) and @whataction = action and @whatid = uid and @whatprot = protecttype
  2343.                delete #tmp where action = @whataction and @whatid = uid
  2344.                select @whataction = min(action) from #tmp
  2345.                select @whatid = uid from #tmp where action = @whataction
  2346.                select @whatprot = protecttype from #tmp where uid = @whatid and action = @whataction
  2347.          end
  2348.          delete #tmp
  2349.       end
  2350.  
  2351.         /* Increment our "fake cursor" column and get the next one. */
  2352.         delete #objs where id = @id
  2353.         select @id = min(id) from #objs
  2354.     end
  2355.  
  2356.     /*
  2357.      * Organize so that the non-collist privileges are returned first.. this allows
  2358.      * scripting to combine them.  sysprotects.action is tinyint, so the hibyte won't conflict.
  2359.      */
  2360.  
  2361.     update #output set action = action | 0x10000000 where colid <> 0
  2362.  
  2363.     /*
  2364.      *  BUG 58252  
  2365.      *  Delete the columns that was droped
  2366.      */
  2367.     delete from #output where colid not in (0, -1) and col_name(id, colid) is null
  2368.  
  2369.  
  2370.     /*
  2371.      * Order output by uid so Public will script before other groups (we need to script privs for public before
  2372.      * other groups, before users; otherwise sysprotects doesn't hold onto things right).  Sub-order is by object id
  2373.      * so we know when we're done with one object and onto the next, then by protecttype to group all GRANTs and
  2374.      * REVOKEs together, and lastly by action (including ORDER_ACTION_BIT so scripting can be more efficient)
  2375.      * because we may have multiple rows for columns.
  2376.      */
  2377.  
  2378.     set nocount off
  2379.    if (@mode not like N'col%') begin
  2380.       /* Mode is not 'column', do the regular stuff */
  2381.        select p.action & ~convert(int, 0x10000000), N'column' = col_name(p.id, p.colid), p.uid, N'username' = user_name(p.uid),
  2382.                p.protecttype, o.name, N'owner' = user_name(o.uid), p.id, N'grantor' = user_name(p.grantor)
  2383.              from #output p, dbo.sysobjects o
  2384.              where o.id = p.id
  2385.              order by p.uid, p.id, p.protecttype, p.action
  2386.    end else
  2387.    /* Below are spcial cases for column level permissions */
  2388.    if (@objname is null) and (@grantee is not null) and (@rollup = 0) begin
  2389.       /* 8.0, special path to get column level permissions from all objects on the specified user */
  2390.       select N'ObjectName' = o.name, N'Owner' = user_name(o.uid), N'ColumnName' = col_name(p.id, p.colid), o.sysstat & 0x0f, p.id,
  2391.              p.action & ~convert(int, 0x10000000), p.protecttype
  2392.              from #output p, dbo.sysobjects o
  2393.              where p.id = o.id and p.uid = user_id(@grantee) and col_name(p.id, p.colid) is not null
  2394.              order by p.uid, p.id, p.protecttype, p.action
  2395.     end else if (@objname is not null) and (@grantee is not null) and (@rollup = 0) begin
  2396.       /* 8.0, mode 'column', and grantee != null, we want column level permissions on this object for this user */
  2397.       select N'column' = col_name(p.id, p.colid), N'owner' = user_name(o.uid), N'username' = user_name(p.uid), o.sysstat & 0x0f, p.id,
  2398.              p.action & ~convert(int, 0x10000000), p.protecttype
  2399.              from #output p, dbo.sysobjects o
  2400.              where o.id = p.id and p.uid = user_id(@grantee) and col_name(p.id, p.colid) is not null
  2401.              order by p.uid, p.id, p.protecttype, p.action
  2402.    end else if (@objname is not null) and (@grantee is null) and (@rollup = 0) begin
  2403.       /* 8.0, mode 'column', and grantee = null, we want column level permissions on this object for all users */
  2404.       select N'column' = col_name(p.id, p.colid), N'owner' = user_name(o.uid), N'username' = user_name(p.uid), o.sysstat & 0x0f, p.id,
  2405.              p.action & ~convert(int, 0x10000000), p.protecttype
  2406.              from #output p, dbo.sysobjects o
  2407.              where o.id = p.id and col_name(p.id, p.colid) is not null
  2408.              order by p.uid, p.id, p.protecttype, p.action
  2409.    end else if (@objname is null) and (@grantee is not null) and (@rollup <> 0) begin
  2410.       /* 8.0, roll up version of the special path to get column level permissions from all objects on the specified user */
  2411.       select distinct N'ObjectName' = o.name, N'owner' = user_name(o.uid),
  2412.              N'Select' = (case when ((p.action & ~convert(int, 0x10000000))=193) then 1 else 0 end),
  2413.              N'Update' = (case when ((p.action & ~convert(int, 0x10000000))=197) then 1 else 0 end),
  2414.              N'Type' = p.protecttype
  2415.              from #output p, dbo.sysobjects o
  2416.              where p.id = o.id and p.uid = user_id(@grantee) and col_name(p.id, p.colid) is not null
  2417.              order by o.name
  2418.    end else if (@objname is not null) and (@grantee is null) and (@rollup <> 0) begin
  2419.       /* 8.0, roll up version of the special path to return column level permissions on this object for all users */
  2420.       select distinct N'UserName' = user_name(p.uid),
  2421.              N'Select' = (case when ((p.action & ~convert(int, 0x10000000))=193) then 1 else 0 end),
  2422.              N'Update' = (case when ((p.action & ~convert(int, 0x10000000))=197) then 1 else 0 end),
  2423.              N'Type' = p.protecttype
  2424.              from #output p, dbo.sysobjects o
  2425.              where o.id = p.id and col_name(p.id, p.colid) is not null
  2426.              order by user_name(p.uid)
  2427.    end else begin
  2428.       raiserror 55555 N'Invalid parameter combinations.'
  2429.         return 1
  2430.    end
  2431. go
  2432. /* End sp_MSobjectprivs */
  2433.  
  2434.  
  2435. exec sp_MS_marksystemobject sp_MSscriptdb_worker
  2436. go
  2437. exec sp_MS_marksystemobject sp_MStablekeys
  2438. go
  2439. exec sp_MS_marksystemobject sp_MSloginmappings
  2440. go
  2441. exec sp_MS_marksystemobject sp_MSdbuseraccess
  2442. go
  2443. exec sp_MS_marksystemobject sp_MSobjectprivs
  2444. go
  2445. exec sp_MS_marksystemobject sp_MSforeachdb
  2446. go
  2447. exec sp_MS_marksystemobject sp_MSforeachtable
  2448. go
  2449.  
  2450.  
  2451. grant execute on sp_MSscriptdb_worker to public
  2452. grant execute on sp_MStablekeys to public
  2453. grant execute on sp_MSloginmappings to public
  2454. grant execute on sp_MSdbuseraccess to public
  2455. grant execute on sp_MSobjectprivs to public
  2456. grant execute on sp_MSforeachdb to public
  2457. grant execute on sp_MSforeachtable to public
  2458.  
  2459.  
  2460. --------------------------------------------------------------------------------
  2461. -- END SQLDMO SECTION
  2462.     
  2463. --------------------------------------------------------------------------------
  2464.  
  2465.  
  2466.  
  2467.  
  2468. --------------------------------------------------------------------------------
  2469. -- END OF FILE: Turn off marking of system objects.
  2470. --    DO NOT ADD ANYTHING AFTER THIS POINT
  2471. --------------------------------------------------------------------------------
  2472. exec sp_MS_upd_sysobj_category 2
  2473. go
  2474.  
  2475. exec sp_configure 'allow updates',0
  2476. go
  2477.  
  2478. reconfigure with override
  2479. go
  2480.